付付的100刷题计划7——单调栈

503. 下一个更大元素 II

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


题目的两个重点:如何求下一个更大的元素和如何实现循环数组

思路:

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

单调栈

单调栈是说栈里面的元素从栈底到栈顶是单调递增或者单调递减的(类似于汉诺塔)。
本题应该用「单调递减栈」来实现。单调栈中保存的是下标,从栈底到栈顶的下标在数组nums 中对应的值是单调不升的。
对于「找最近一个比当前值大/小」的问题,都可以使用单调栈来解决。

求下一个更大的元素

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

实现循环数组

循环数组?就是说数组的最后一个元素的下一个元素是数组的第一个元素,形状类似于「环」。

一种实现方式是,把数组复制一份到数组末尾,这样虽然不是严格的循环数组,但是对于本题已经足够了,因为本题对数组最多遍历两次。
另一个常见的实现方式是,使用取模运算可以把下标 i 映射到数组 nums 长度的 0 −N 内

代码

栈里面需要保存元素在数组中的下标,而不是具体的数字。因为需要根据下标修改结果数组 res。

class Solution(object):
    def nextGreaterElements(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        N = len(nums)
        res = [-1] * N
        stack = []
        for i in range(N * 2):
            while stack and nums[stack[-1]] < nums[i % N]:
                res[stack.pop()] = nums[i % N]
            stack.append(i % N)
        return res

另一种:

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        N=len(nums)
        mnt_stack=[] # 存储未更新的下标
        res=[-1]*N # 存储结果
        
        for i in range(2*N-1):
            while len(mnt_stack)>0 and nums[i%N]>nums[mnt_stack[-1]%N]:
                res[(mnt_stack.pop(-1))%N]=nums[i%N]
            mnt_stack.append(i) #把当前最大元素对应索引入栈    

        return res

注意:

循环两次:因为是根据更大元素这个“结论”反推前面更小元素的赋值,第一次循环中的元素要在第二次循环中才能寻找完一遍数组,做到“首尾相顾”。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值