이럴 때 써요
- 각 원소의 '다음 큰 수' 또는 '이전 큰 수'를 구할 때
- 오른쪽에서 처음으로 자기보다 큰(작은) 값이 언제 나오는지 물을 때
- 매번 뒤를 다시 훑으면
O(n^2)이라 시간 초과가 나는 문제일 때 - 온도가 며칠 뒤 오르는지, 주가가 언제 회복되는지 같은 '기다림' 문제일 때
개념
아직 답(다음 큰 수)을 못 찾은 인덱스를 스택에 쌓아 둬요. 새 원소를 만날 때마다, 스택 맨 위가 가리키는 값보다 지금 값이 더 크면 그게 바로 그 원소의 답이에요. 답을 채우면서
pop 하고, 다 채웠으면 지금 인덱스를 push 해요.스택에는 항상 값이 단조 감소하는 인덱스들만 남아요(그래서 모노토닉이에요). 각 원소는 딱 한 번 들어가고 한 번 나오니, 전체가 O(n)이에요. 매번 뒤를 다시 훑는 O(n^2) 을 스택 하나로 없애는 거예요."[3, 1, 2, 4] 의 다음 큰 수" — 스택엔 인덱스를 쌓아요nums = [3, 1, 2, 4] , 답 res = [-1, -1, -1, -1]i=0 (3) : 스택 비어 있음 → push 0 스택 [0]i=1 (1) : nums[0]=3 > 1 → 안 큼, push 1 스택 [0, 1]i=2 (2) : nums[1]=1 < 2 → res[1]=2, pop 스택 [0]nums[0]=3 > 2 → 안 큼, push 2 스택 [0, 2]i=3 (4) : nums[2]=2 < 4 → res[2]=4, pop 스택 [0]nums[0]=3 < 4 → res[0]=4, pop 스택 []push 3 스택 [3]스택에 남은 3 은 답 없음 → res = [4, 2, 4, -1]
패턴 코드
모노토닉 스택으로 다음 큰 수 구하기스택엔 아직 답을 못 찾은 인덱스만 남고, 값은 항상 단조 감소해요.
javascriptCopy codefunction nextGreater(nums) {const res = new Array(nums.length).fill(-1);const stack = []; // 아직 답을 못 찾은 인덱스들for (let i = 0; i < nums.length; i++) {// 지금 값이 스택 맨 위 값보다 크면, 그게 그 원소의 답이에요while (stack.length > 0 && nums[i] > nums[stack[stack.length - 1]]) {const j = stack.pop();res[j] = nums[i];}stack.push(i);}return res; // 스택에 남은 자리는 -1 그대로예요}