DSA Stacks

Next Greater Element IV

Two monotonic stacks — first finds the next greater; the second collects those popped to find the second.

Hard
Time O(n) Space O(n)
LeetCode
4 min read
monotonic-stack

Problem#

For each index i, return the second strictly greater element to the right — i.e., the value at j where j is the smallest index such that there exist at least two indices k > i with nums[k] > nums[i] and j is the second such index. Return -1 if no such element exists.

Examples#

  • nums = [2,4,0,9,6][9,6,6,-1,-1]
  • nums = [3,3][-1,-1]

Constraints#

  • 1 <= nums.length <= 10^5, 0 <= nums[i] <= 10^9.

Approach#

Use two monotonic decreasing stacks. Stack s1 finds first-next-greater as usual. When s1 pops an index, instead of finalizing, move it to a holding buffer. Stack s2 is checked first: anything popped from s2 is the second-next-greater. To preserve ordering on s2, drain s1 popped elements in increasing order of value (i.e., bottom up) before merging.

Solution#

Next Greater Element IV
class Solution {
public:
vector<int> secondGreaterElement(vector<int>& nums) {
int n = nums.size();
vector<int> ans(n, -1);
stack<int> s1, s2;
for (int i = 0; i < n; ++i) {
while (!s2.empty() && nums[s2.top()] < nums[i]) {
ans[s2.top()] = nums[i];
s2.pop();
}
stack<int> tmp;
while (!s1.empty() && nums[s1.top()] < nums[i]) {
tmp.push(s1.top());
s1.pop();
}
while (!tmp.empty()) {
s2.push(tmp.top());
tmp.pop();
}
s1.push(i);
}
return ans;
}
};

Editorial#

s1 is the standard monotone-decreasing stack for “next greater”. Whatever s1 pops at index i has already encountered its first greater (which is nums[i]). Those popped indices are still candidates for “second greater”, so they migrate to s2. The transfer preserves the decreasing order using a temporary buffer, which keeps s2 monotonic and amortized linear overall.

Complexity#

  • Time: O(n).
  • Space: O(n).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.