각 원소 에 대해, 오른쪽에 있으면서 보다 큰 수 중 가장 왼쪽에 있는 수(오큰수)를 찾아야 합니다.
스택 내부를 특정 순서(이 문제에서는 내림차순)로 유지하며, 조건이 맞을 때 '한꺼번에' 처리하는 모노톤 스택 기법을 사용합니다.
NGE[index] 위치에 정확히 값을 기록할 수 있습니다.top에 있는 인덱스의 값보다 크다면?pop을 수행하며 해당 인덱스의 오큰수를 로 확정 짓습니다.-1로 초기화하여 효율적으로 처리합니다.)import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
int N = Integer.parseInt(br.readLine());
int[] A = new int[N];
int[] NGE = new int[N];
// 아직 오큰수를 찾지 못한 경우를 위해 -1로 초기화
Arrays.fill(NGE, -1);
StringTokenizer st = new StringTokenizer(br.readLine());
// [Key] 인덱스를 담을 모노톤 스택 (ArrayDeque 권장)
Deque<Integer> stack = new ArrayDeque<>();
for (int i = 0; i < N; i++) {
A[i] = Integer.parseInt(st.nextToken());
// 스택이 비어있지 않고, 현재 값이 스택 top이 가리키는 값보다 크다면
// 현재 값은 '오큰수'가 됨
while (!stack.isEmpty() && A[stack.peek()] < A[i]) {
NGE[stack.pop()] = A[i];
}
// 현재 인덱스를 스택에 추가
stack.push(i);
}
// 출력 최적화: StringBuilder 사용
StringBuilder sb = new StringBuilder();
for (int val : NGE) {
sb.append(val).append(" ");
}
bw.write(sb.toString());
bw.flush();
}
}
}
A[i]가 더 클 때) 모노톤이 깨지면서 그동안 쌓여있던 작은 값들의 오큰수가 결정되는 원리입니다.System.out.print를 쓰면 안 됩니다. 반드시 StringBuilder나 BufferedWriter를 사용해야 시간 초과를 피할 수 있습니다.11003번에서 다뤘던 모노톤 덱과 이번 모노톤 스택은 '불필요한 비교를 줄이고 유의미한 데이터만 자료구조에 유지한다'는 핵심 아이디어를 공유합니다. 선형 자료구조를 활용한 시간 복잡도 최적화의 정수를 맛볼 수 있는 좋은 문제였습니다.