本文已参与「新人创作礼」活动,一起开启掘金创作之路。
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
示例 1:
输入: [1,2,1] 输出: [2,-1,2] 解释: 第一个 1 的下一个更大的数是 2; 数字 2 找不到下一个更大的数; 第二个 1 的下一个最大的数需要循环搜索,结果也是 2。 注意: 输入数组的长度不会超过 10000。
思路:
本题也可以使用单调栈来做,但是和上一题不太一样,因为这道题是一个循环数组,以及这个数组中的数是可以重复的,所以需要变化一下思路,不能完全和上一道题一样.
首先处理这个循环问题,这个很简单,使用对n去摸来进行处理变为原来正常的下标.然后是重复的数这个问题,我们虽然要继续使用单调栈的方法,但是不用再继续使用哈希表了,因为没这个必要(上一题是因为可以直接把数存入哈希表去映射,但是这道题因为有重复的数所以需要把对应的下标存入,因为下标是按照顺序来的,所以没必要使用哈希表了,直接用数组就可以了)
把下标从0开始压入栈中,然后对下一个数进行判断是否栈非空并且nums[i]大于nums[stk.top()],如果大于就把res[栈顶的数]赋值为nums[i],这样就找到了下一个更大的数了.然后把栈顶的元素弹出
但是这里的循环次数需要注意一下,不是n而应该是2*n-1,因为需要用新的数组接在原来的数组后面来模拟循环数组.
这里还有一点和上一题不太一样,没有使用while循环来对没有对应的数进行赋值-1,而是一开始就对res数组进行全部赋值为-1,如果没有对应的数存在就不会被替代掉,就还是-1,符合题目的要求.(那么上一题为啥不能这么做呢,还是这个问题,因为上一题是把数本身存入map中而不是下标,因为数的范围实在是太大,所以不能这么投机取巧)
代码区:
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
stack<int> stk;
int n = nums.size();
vector<int> res(n, -1);//全部赋值为-1,来对应没找到更大的数的情况
for(int i = 0; i < 2 * n - 1; i++){//把数组从圆圈重新"拉直"
while(!stk.empty() && nums[i % n] > nums[stk.top()]){//找到更大的数这里把下标存入res的下标中,这样下面才可以直接按照顺序来遍历
res[stk.top()] = nums[i % n];
stk.pop();
}
stk.push(i % n);
}
return res;
}
};
新手上路,有错请指正;