크기가 N인 수열 A = A1, A2, ..., AN이 있다. 수열의 각 원소 Ai에 대해서 오큰수 NGE(i)를 구하려고 한다. Ai의 오큰수는 오른쪽에 있으면서 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의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.
총 N개의 수 NGE(1), NGE(2), ..., NGE(N)을 공백으로 구분해 출력한다.
4
3 5 2 7
5 7 7 -1
4
9 5 4 8
-1 8 8 -1
stack을 이용하는 문제이다. 무조건 리스트의 오른쪽을 비교하라는 문제가 나온다면, stack을 이용하도록 하자. 이 문제의 핵심은 리스트를 탐색하면서 값들을 비교해 보는 것이다. 왜 굳이 stack을 쓰면서 탐색을 할까? 만약 예제 입력 2 처럼 9 5 4 8 이란 숫자가 들어왔다. 그렇다면 9 5 4 까지는 감소하는 부분 수열이기 때문에 오큰수가 나오지 않아서 stack에 계속해서 집어 넣게 된다. 그렇다면 stack에 가장 끝에 쌓여있는 숫자는 가장 작은 숫자가 되는데, 이러한 가장 작은 숫자가 리스트의 다음 수와 비교하여 4라는 숫자가 리스트의 숫자보다 크다면, 나머지 stack에 쌓여있는 숫자들은 비교할 필요도 없게 된다. 반대로 4라는 가장 작은 숫자가 8과 비교하였을 때 8이 더 크면 4를 빼고 다시 순차적으로 5랑 비교를 하고, 9랑 비교를 하는 것이다. 이러한 메커니즘이 stack이다.
import sys
N = int(sys.stdin.readline())
NEG = list(map(int, sys.stdin.readline().split()))
stack = []
ans = [-1] * N
for i in range(N):
while stack and (stack[-1][0] < NEG[i]):
val, index = stack.pop()
ans[index] = NEG[i]
stack.append((NEG[i], i))
print(*ans)
# index 함수는 시간 복잡도가 O(n)이다.