LeetCode破解之下一个更大元素 II

389 阅读2分钟

「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

题目描述

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

示例 1:

输入: [1,2,1] 输出: [2,-1,2] 解释: 第一个 1 的下一个更大的数是 2; 数字 2 找不到下一个更大的数; 第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

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

解法1:单调栈

具体实现:

  1. 遍历数组,为了保证所有数据全部探寻到,所有需要遍历两次,nums.length * 2,用取模处理越界问题。
  2. 需要采用单调栈,并且从栈顶到栈底,单调递减
  3. 递减的单调栈,可以保证外部元素大于栈顶元素时,可以保证出栈的元素都比外部元素。
public int[] nextGreaterElements(int[] nums) {
        int len = nums.length;
        int[] res = new int[len];
        Arrays.fill(res, -1);
        Deque<Integer> stack = new LinkedList<>();
        for (int i = 0; i < len * 2 - 1; i++) {
            while (!stack.isEmpty() && nums[stack.peek()] < nums[i % len]) {
                res[stack.pop()] = nums[i % len];
            }
            stack.push(i % len);
        }
        return res;
    }

解法2:动态规划

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n=nums.length;
        int[] a=new int[n];
        Arrays.fill(a,Integer.MIN_VALUE);
        for(int i=n-1;i>=0;i--){
            int j;
            for(j=1;j<n;j++){
                int p=(i+j)%n;
                if(nums[p]>nums[i]){
                    a[i]=nums[p];
                    break;
                }
                else if(a[p]>nums[i]){
                    a[i]=a[p];
                    break;
                }
            }
            if(j==n){
                a[i]=-1;
            }
        }
        return a;
    }
}

总结

其实我们可以发现,大体思路上,就是入栈前先排个序。如果当前元素比栈顶元素小,正常入栈。如果当前元素比栈顶元素大,那么关键点就来了,说明当前元素至少是栈顶元素的下一个更大元素,将栈顶元素出栈,当前元素再和接下来的栈顶元素比较,小->入栈,大->继续栈顶出栈,出栈的这些就算是找到下一个更大元素了,更新即可。这个单调栈保存的其实是数组下标。