给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x
的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1
。
示例 1:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
注意: 输入数组的长度不会超过 10000
。
解答
先试试暴力,居然过了:
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int len = nums.size();
if(len < 0)
return {};
vector<int> result(len);
for(int i = 0; i < len; i++){
result[i] = search(nums, i);
}
return result;
}
int search(vector<int>& nums, int index){
int i = index;
while(i < nums.size()){
if(nums[i] > nums[index])
return nums[i];
i++;
}
i = 0;
while(i < index){
if(nums[i] > nums[index])
return nums[i];
i++;
}
return -1;
}
};
参考官方题解,采用单调栈的思路。首先由于循环数组中大于该元素的下一个元素可能出现在数组前端,因此我们可以将数组复制一份到尾部,这样就能保证都出现在后面了。当然实际处理时只需要对索引取模就行。
维护一个单调不增(递减或等于)的栈,栈内存储索引,这样每当遍历到一个元素cur_num
大于栈顶对应元素时,就说明栈顶索引元素的下一个更大元素为cur_num
。
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int len = nums.size();
vector<int> result(len, -1);
stack<int> s;
for(int i = 0; i < 2 * len; i++){
int cur_num = nums[i % len];
while( !s.empty() && nums[s.top()] < cur_num ){
result[s.top()] = cur_num;
s.pop();
}
if( i < len ){
s.push(i);
}
}
return result;
}
};