1.题目描述
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
链接:leetcode-cn.com/problems/ne…
示例1:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
示例2:
输入:[3,-2,-1,2]
输出:[-1,-1,2,3]
解释:3的后面没有比它大1的数,返回-1,-2的情况也是如此;
-1的后面一个比它更大的数为2,数组里-1对应的下标的数为2,
最后2的寻找需要循环数组,找到3.
2.题目分析
1.目标数组寻找的是最近的比当前数更大的数,找到后不需继续。
2. 目标数组存储包括更大的数和没有找到的-1。
3.思路及算法:我们可以使用单调栈解决本题。单调栈中保存的是下标,从栈底到栈顶的下标在数组里,本题如果暴力求解,对于每个元素都向后去寻找比它更大的元素,那么时间复杂度为(O^2);如果数组的前半部分是单调不增的,那么会有很大的计算资源的浪费.对于「找最近一个比当前值大/小」的问题,都可以使用单调栈来解决。单调栈就是在栈的基础上维护一个栈内元素单调。可以做到O(n)的复杂度,我们**将当前还没得到答案的下标暂存于栈内,从而实现「被动」更新答案。**也就是说,栈内存放的永远是还没更新答案的下标。
3.解决方法
暴力法:
class Solution { public int[] nextGreaterElements(int[] nums)
{ int[] res = new int[nums.length];//输出目标大小为数组长度
for (int i = 0; i < nums.length; i++)
{ boolean flag=false;//设置flag 方便标志没有更大值的数
for (int j = 1; j < nums.length; j++) {
if (nums[(i+j)%nums.length]>nums[i]){//(i+j)%... 实现了循环数组
flag=true;
res[i]=nums[(i+j)%nums.length];//找到存入
break;//一旦找到就执行下一个数的寻找,跳出当前循环。
}
}
if (flag==false){
res[i]=-1;//没有找到的设置-1 }
}
return res;
}}
单调栈法:
class Solution { public int[] nextGreaterElements(int[] nums) {
int[] ans = new int[nums.length];
Arrays.fill(ans, -1);//初始化输出数组,都为-1
Deque<Integer> stack = new ArrayDeque<>();//设置栈存储数组下标
for (int i = 0; i < nums.length; i = (i + 1) % nums.length) {//(i+1)%...循环数组
while (!stack.isEmpty() && nums[i] > nums[stack.peek()]) {
/*栈非空并且当前元素大于入栈元素的话,
输出数组得到从栈顶得到对应的正确下标,
将该下标的值设置为更大的数*/
ans[stack.pop()] = nums[i];
}
if (!stack.isEmpty() && i == stack.peek()) break;//一旦找到,退出并执行下一循环
if (stack.isEmpty() || i > stack.peek()) stack.push(i);//已经找到的数的下标出栈
}
return ans;
}
}
4.小结
本题难度中等,主要是想考察大家对单调栈的理解。要将 O(n^2)算法优化为 O(n) 算法,因此需要将「主动」获取答案转换为「被动」更新 我们需要使用数据结构保持那些「尚未更新」的位置下标,由于题目要求的是找「下一个更大的元素」,因此使用栈来保存 「被动」更新答案的逻辑导致了我们栈内元素单调 。思路并不难,只是单调栈出现的不多,大家需要扩展知识面,多多了解各种数据结构的不同用法。
本文水平有限,如有错误,欢迎大家指正。相关链接:https://leetcode- cn.com/problems/next-greater-element-ii/solution/cong-po-su-jie-fa-de-jiao-du-qu-li-jie-d-trht/
本文正在参与[掘金3月闯关活动],点击查看juejin.cn/post/693450…9
微信搜索"掘金酱@北比" ,入群可抽得奖励。