최초로 백준 골드 문제를 풀게 되었습니다. 그런데 해당 문제는 LeetCode 739문제와 매우 유사합니다. 해당 문제 정보는 다음 링크에서 확인할 수 있습니다. 그럼 살펴보도록 하겠습니다.
크기가 N인 수열 A = 이 있다. 수열의 각 원소 에 대해서 오큰수 NGE(i)를 구하려고 한다. 의 오큰수는 오른쪽에 있으면서 Ai보다 큰 수 중에서 가장 왼쪽에 있는 수를 의미한다. 그러한 수가 없는 경우에 오큰수는 -1이다.
예를 들어, A = [3, 5, 2, 7]인 경우 NGE(1) = 5, NGE(2) = 7, NGE(3) = 7, NGE(4) = -1이다. A = [9, 5, 4, 8]인 경우에는 NGE(1) = -1, NGE(2) = 8, NGE(3) = 8, NGE(4) = -1이다.
입력
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에 수열 A의 원소 (1 ≤ ≤ 1,000,000)이 주어진다.
출력
총 N개의 수 NGE(1), NGE(2), ..., NGE(N)을 공백으로 구분해 출력한다.
예제 입력 1 복사
4
3 5 2 7
예제 출력 1 복사
5 7 7 -1
예제 입력 2 복사
4
9 5 4 8
예제 출력 2 복사
-1 8 8 -1
크기가 N인 수열 A = 이 있습니다. 수열의 각 원소 에 대해서 오큰수 NGE(i)를 구하려고 합니다. 의 오큰수는 오른쪽에 있으면서 Ai보다 큰 수 중에서 가장 왼쪽에 있는 수를 의미합니다. 그러한 수가 없는 경우에 오큰수는 -1이라고 합니다.
즉 현재 인덱스의 값보다 큰 인덱스 중 가장 가까이(작은) 인덱스에 해당하는 값이 현재 인덱스의 오큰수입니다.
뭔가 감이 오지 않나요?
현재 위치 이후에 값들중 현재 위치 값보다 큰 값에만 반응을 합니다. 과거는 의미가 없는 것이며 현재 위치로부터 미래의 값들과 비교하는것입니다. 바로 이것이 LIFO원리를 이용하는것입니다!
현재 위치 값이 수열 A를 제일 최근에 순회한 값일테니까요!
더 자세히 분석하기 전 입출력 조건을 살펴보도록 하겠습니다.
사실, Step1에서 거의 다 분석이 완료되었습니다.
스택 자료구조를 활용해서 구현하면 되고, 이것은 수열 A의 크기만큼의 시간 복잡도로 구현될 것입니다. 따라서 N 크기에도 충분히 여유가 있는것을 알 수 있습니다.
그렇다면 스택 자료구조로 구체적으로 어떻게 구현하면 될 지 살펴 보도록 하겠습니다.
구체적인 접근법:
이 방법의 핵심은 모든 원소를 한 번씩만 검사하고, 스택에서 pop 연산도 에 수행되므로 전체 시간 복잡도가 입니다.
import sys
N = int(sys.stdin.readline().strip()) # 수열의 크기 입력
A = list(map(int, sys.stdin.readline().split())) # 수열 입력
def sol(N, A):
NGE = [-1] * N # 결과 배열을 -1로 초기화
stack = [] # 인덱스를 저장할 스택 초기화
for i in range(N):
# 현재 값 A[i]가 스택의 top에 있는 인덱스의 값보다 크면 오큰수를 찾은 것
while stack and A[stack[-1]] < A[i]:
NGE[stack.pop()] = A[i]
stack.append(i) # 현재 인덱스를 스택에 저장
# 결과를 공백으로 구분된 문자열로 변환하여 반환
return ' '.join(map(str, NGE))
# 결과 출력
print(sol(N, A))
N
과 수열 A
를 입력받습니다.NGE
배열은 1로 초기화되며, 이는 모든 값이 오큰수를 아직 찾지 못했다는 의미입니다.A[i]
가 스택의 top에 있는 값보다 크다면, 오큰수 조건을 만족한 것이므로 NGE
배열을 업데이트하고 스택을 pop합니다.NGE
배열의 결과를 공백으로 구분된 문자열로 반환합니다.이 문제는 스택을 활용해 효율적으로 오큰수를 찾는 문제로, 각 원소를 한 번씩만 탐색하므로 O(N)의 시간 복잡도로 해결할 수 있습니다. 스택을 활용하면 과거의 데이터를 저장하면서 현재 값과 비교하는 LIFO구조를 잘 이용할 수 있다는 점이 핵심입니다. 또한, 결과를 저장하는 배열과 스택을 활용해 코드가 직관적이고 간결하게 구성됩니다. 이 문제를 통해 스택을 활용한 탐색 최적화 방법을 다시 한 번 익힐 수 있었습니다.
전체 코드는 다음 링크에서 확인할 수 있습니다.
읽어주셔서 감사합니다!
어제보다 나은 개발자가 될거야!