题目:
给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。
数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。
示例 1:
输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/next-greater-element-ii
思路:
本题是将数组变为循环数组:因此单调栈的查找需要 2*N的长度;
创建一个新的数组,然后进行单调栈的判断,同时需要判断下标是否越界
代码:
1)单调栈思想
class Solution {
public int[] nextGreaterElements(int[] nums) {
//两个数组拼成一个,时间复杂度为 o(2N)
int l = nums.length;
int[] nums1 = new int[2 * l];
//将新的数组赋值
for(int i = 0;i < 2 * l;i++){
nums1[i] = nums[i % l];
}
int[] res = new int[l];
Arrays.fill(res,-1);
Stack<Integer> stack = new Stack<>();
for(int i = 0;i < 2 * l;i++){
while(!stack.isEmpty() && nums1[i] > nums1[stack.peek()]){
int index = stack.pop();
if(index < l){
res[index] = nums1[i];
}
}
stack.push(i);//这次往里面放下标
}
return res;
}
}
同样可以不构件新的数组,直接在原有的数组基础上,每次都取余即可:
class Solution {
public int[] nextGreaterElements(int[] nums) {
//两个数组拼成一个,时间复杂度为 o(2N)
int l = nums.length;
int[] res = new int[l];
Arrays.fill(res,-1);
Stack<Integer> stack = new Stack<>();
for(int i = 0;i < 2 * l;i++){
while(!stack.isEmpty() && nums[i % l] > nums[stack.peek() % l]){
int index = stack.pop();
if(index < l){
res[index] = nums[i % l];
}
}
stack.push(i);//这次往里面放下标
}
return res;
}
}
可以继续简化,判断条件
class Solution {
public int[] nextGreaterElements(int[] nums) {
//两个数组拼成一个,时间复杂度为 o(2N)
int l = nums.length;
int[] res = new int[l];
Arrays.fill(res,-1);
Stack<Integer> stack = new Stack<>();
for(int i = 0;i < 2 * l;i++){
while(!stack.isEmpty() && nums[i % l] > nums[stack.peek()]){
res[stack.pop()] = nums[i % l];
}
if(i < l)
stack.push(i);//这次往里面放下标
}
return res;
}
}