Leetcode 503 下一个更大元素 II |刷题打卡

191 阅读2分钟

一、题目描述:

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例

输入: [1,2,1]

输出: [2,-1,2]

解释: 第一个 1 的下一个更大的数是 2;

数字 2 找不到下一个更大的数;

第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

注意: 输入数组的长度不会超过 10000。

二、思路分析:

一般我们会想到暴力法,对数组中每个元素都向后去寻找比它更大的元素,时间复杂度 O(N^2) 会超时。

通过单调栈,来获取下一个更大元素

  1. 可以使用单调栈解决本题。单调栈中保存的是数组nums的下标,从栈底到栈顶的下标在数组 nums 中对应的值是单调递减的。维护一个单调递减栈。

  2. 每次移动到数组中的一个新的位置i,我们就将当前单调栈中所有对应值小于 nums[i]的下标弹出单调栈,这些值的下一个更大元素就是nums[i]。

  3. 然后将位置 i 入栈。

来模拟以下过程

  1. new Stack < >
  2. nums[0]是1, Stack为空,下标入栈,Stack< 0 >,
  3. nums[1]是2, Stack不空,nums[栈顶元素值(现在是0)]=1<2,如果入栈,不满足单调递减栈,那么就把下标0弹出,下标1入栈。这时弹出的(0)对应的nums[0]元素的[下一个更大元素]就是2。下标1入栈。
  4. nums[2]是1,Stack不空, nums[栈顶元素(现在是1)]=2>1, 如果入栈,符合单调递减栈。

如果理解困难,再举例一试 nums={5,4,6}, 当5,4的下标依次入栈时,符合栈单调递减,但是当6的下标入栈时候,6比他们都大,他们都的出栈,否则不满足单调递减。6把他们都逼走了。简而言之,nums[被逼走的下标]的下一个更大元素就是把他们逼走的元素。

那么问题又来了,一遍循环肯定不够,数组的最后元素怎么办,说好的循环数组呢?

办法就是复制数组的前n-1个元素,到nums的后面。这样我们就可以将这个新序列当作普通序列,用单调栈的方法来求解。

三、AC 代码:

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        stack<int> stack;
        vector<int> res(nums.size(), -1);

        for(int i = 0; i <= nums.size()*2; i++)
        {
            
            while(!stack.empty() && nums[i % nums.size()] > nums[stack.top()])
            {
                res[stack.top()] = nums[i % nums.size()];
                stack.pop();
            }
            if(i < nums.size()){
                stack.push(i);
            }
           
        }
        return res;
    }
};

四、总结:

暴力法求解时间复杂度O(N^2), 采用单调栈时间复杂度O(N)。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情