题目
示例:
输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]
解题思路
- 创建一个栈, 遍历这个数组, 记数组元素为
nums[i]
, 然后接下来我们都要维持这个栈的单调性 - 创建一个记录答案的数组ans[], 并全部初始化成-1
- 如果栈空, 那就压入下标i, 注意压入的是下标, 因为有了下标都能得到对应的值nums[i]
- 如果
nums[栈顶] >= nums[i]
, 说明下一个元素并不是更大元素, 那就继续将i
入栈 (注意栈储存的是下标, 比较的时候比较的是下标对应的值) - 如果
nums[栈顶] < nums[i]
, 说明这个元素就是栈顶元素的下一个更大值, 那就让ans[栈顶] = nums[i]
(这个就是nums[栈顶]
的下一个更大元素) - 题目数组是循环数组(
nums[nums.length-1]的下一个元素是nums[0]
), 所以至少要遍历数组两次, 才能完成所有元素的操作, 而下标到了nums.length - 1
后我们可以通过取模运算i % nums.length
让下标重新回到开头
这样可能还是有点抽象, 下面是动画演示
GIF
我们以这个为例
输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]
GIF(慢速版本)
我们以这个为例
输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]
GIF(慢慢速版)
代码
public class NextGreaterElements {
//单调栈
public int[] nextGreaterElements(int[] nums) {
Stack<Integer> stack = new Stack<> ();
int[] ans = new int[nums.length];
Arrays.fill(ret, -1);//全初始化成-1
//这里(nums.length*2)-1 或者 nums.length*2都可以
for (int i = 0; i < nums.length * 2 - 1; i++) {
//注意是while 不是 if , 如果nums[i % nums.length]一直大于,那就一直弹出
while (!stack.isEmpty() && nums[stack.peek()] < nums[i % nums.length]) { //如果栈不为空并且新元素无法维持单调栈
ans[stack.pop()] = nums[i % nums.length];
}
//注意nums[i % nums.length]和别人比较完, 也是要入栈的
stack.push(i % nums.length);//入栈的是下标
}
return ans;
}
}