파이썬 코딩테스트 강좌, 오큰수 구하기

안녕하세요! 오늘은 취업 준비생들에게 매우 유용한 알고리즘 문제인 ‘오큰수 구하기’를 소개하고 자세히 설명하는 시간을 가지겠습니다. 이 문제는 스택(Stack)의 개념을 이해하고 활용하는 데 큰 도움이 될 것입니다. 그럼 시작해볼까요?

문제 설명

문제 설명: 주어진 배열에서 각 원소에 대해 “오큰수”를 구하는 문제입니다. “오큰수”는 해당 원소의 오른쪽에 있는 원소 중에서 가장 첫 번째로 크기가 큰 원소를 의미합니다. 만약 그러한 원소가 존재하지 않으면 -1로 표시합니다.

입력: 첫 번째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어지고, 두 번째 줄에는 N개의 자연수 A1, A2, …, AN (1 ≤ Ai ≤ 1,000,000)이 주어집니다.

출력: 각 원소에 대한 오큰수를 한 줄에 하나씩 출력합니다.

예제

입력:

5
2 1 3 4 5

출력:

3
3
4
5
-1

문제 해결 전략

문제를 해결하기 위한 가장 효과적인 방법 중 하나는 스택을 이용하는 것입니다. 스택은 LIFO(Last In, First Out) 구조의 자료구조로, 문제를 해결하는 데 유용하게 사용될 수 있습니다.

스택을 이용한 접근 방법

  1. 비어 있는 스택을 하나 생성합니다.
  2. 주어진 배열을 오른쪽부터 왼쪽으로 탐색하면서 각 원소에 대해 다음을 수행합니다:
    1. 현재 원소와 스택의 최상단 원소를 비교합니다.
    2. 스택의 최상단 원소가 현재 원소보다 크면, 그 원소가 오큰수입니다. 현재 원소에 오큰수를 저장합니다.
    3. 스택의 최상단 원소가 현재 원소보다 작거나 스택이 비어있으면 스택에서 원소를 pop합니다.
    4. 현재 원소를 스택에 추가합니다.
  3. 모든 원소를 탐색한 후, 오큰수가 저장된 결과 배열을 출력합니다.

코드 구현

이제 위의 알고리즘을 파이썬 코드로 구현해보겠습니다.


def find_next_greater_element(arr):
    n = len(arr)
    result = [-1] * n  # 오큰수를 저장할 결과 배열
    stack = []  # 스택 생성

    # 배열을 오른쪽부터 왼쪽으로 탐색
    for i in range(n - 1, -1, -1):
        # 스택의 최상단 원소와 비교
        while stack and stack[-1] <= arr[i]:
            stack.pop()  # 스택에서 pop
        
        # 스택이 비어있지 않다면 오큰수 기록
        if stack:
            result[i] = stack[-1]
        
        # 현재 원소를 스택에 추가
        stack.append(arr[i])

    return result

# 입력 처리
n = int(input())
arr = list(map(int, input().split()))

# 오큰수 구하기
result = find_next_greater_element(arr)

# 결과 출력
for r in result:
    print(r)

코드 설명

위 코드는 주어진 배열에서 각 원소의 오큰수를 찾는 함수입니다. 함수는 다음과 같은 과정을 따릅니다:

  1. 입력으로 받은 배열의 길이를 구하고, 결과를 저장할 배열을 초기화합니다.
  2. 주어진 배열을 오른쪽부터 왼쪽으로 순회합니다.
  3. 현재 원소와 비교하기 위해 스택의 최상단 원소를 확인합니다.
  4. 스택의 최상단 원소가 현재 원소보다 작거나 같으면 스택에서 pop합니다. 이렇게 해서 스택에는 항상 현재 원소보다 큰 값만 남게 됩니다.
  5. 스택이 비어 있지 않다면, 스택의 최상단 원소가 현재 원소의 오큰수가 됩니다. 이것을 결과 배열에 기록합니다.
  6. 현재 원소를 스택에 추가합니다.

복잡도 분석

시간 복잡도는 O(N)입니다. 각 원소는 스택에 한 번 추가되고 한 번 제거되므로, 전체적으로 N번의 연산이 필요합니다. 공간 복잡도는 O(N)으로 결과 배열과 스택을 저장하는 데 필요한 공간을 고려해야 합니다.

결과 예시

이제 코드의 일부 테스트 케이스를 확인해보겠습니다. 위에서 제시한 예제를 사용하여 오큰수를 구해보겠습니다.


# 입력 예제
# 5
# 2 1 3 4 5

print(find_next_greater_element([2, 1, 3, 4, 5]))  # 출력: [3, 3, 4, 5, -1]

결론

이번 시간에는 ‘오큰수 구하기’ 문제를 해결하는 과정을 살펴보았습니다. 스택을 사용하여 효율적으로 문제를 해결하고, 실제 코드를 통해 그 원리를 적용해 보았습니다. 이러한 방식의 문제 해결은 실제 코딩 테스트와 알고리즘 면접에서 매우 유용하니 꼭 연습해 보시기 바랍니다.

다음 시간에는 또 다른 알고리즘 문제를 가지고 찾아오겠습니다. 감사합니다!