解题记录 LeetCode 下一个更大元素 II 单调栈

题目链接: https://leetcode-cn.com/problems/next-greater-element-ii/
题意:
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
思路:
我们可以使用单调栈解决本题。单调栈中保存的是下标,从栈底到栈顶的下标在数组nums 中对应的值是单调不升的。
每次我们移动到数组中的一个新的位置 i,我们就将当前单调栈中所有对应值小于nums[i] 的下标弹出单调栈,这些值的下一个更大元素即为 nums[i](证明很简单:如果有更靠前的更大元素,那么这些位置将被提前弹出栈)。随后我们将位置 i 入栈。
但是注意到只遍历一次序列是不够的,例如序列 2,3,1,最后单调栈中将剩余 3,1,其中元素 1的下一个更大元素还是不知道的。
一个朴素的思想是,我们可以把这个循环数组「拉直」,即复制该序列的前 n−1 个元素拼接在原序列的后面。这样我们就可以将这个新序列当作普通序列,用上文的方法来处理。
而在本题中,我们不需要显性地将该循环数组「拉直」,而只需要在处理时对下标取模即可。
注意 这里是正向遍历 思路和逆向遍历略有区别: 如果下一个元素大于当前栈顶且栈不为空, 那么就可以增加一个键值对, 然后出栈和入栈, 如果为空, 就直接入栈
最后,当数组nums2中所有元素都考察完毕时,如果栈不为空,说明栈中的元素没有找到下一个更大的元素, 根据题意其对应的value为-1。

class Solution {
    
    
    public int[] nextGreaterElements(int[] nums) {
    
    
        int n = nums.length;
        int[] ret = new int[n];
        Arrays.fill(ret, -1);
        Deque<Integer> stack = new LinkedList<Integer>();
        for (int i = 0; i < n * 2 - 1; i++) {
    
    
            while (!stack.isEmpty() && nums[stack.peek()] < nums[i % n]) {
    
    
                ret[stack.pop()] = nums[i % n];
            }
            stack.push(i % n);
        }
        return ret;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45560445/article/details/118486700
今日推荐