单调栈-递增

单调栈-牛客

思路

  • 单调栈
    单调栈是指栈内元素是具有有单调性的栈,单调栈在入栈的时候,需要将待入栈的元素和栈顶元素进行对比,看待加入栈的元素入栈后是否会破坏栈的单调性,如果不会,直接入栈;否则一直弹出到满足条件为止。
    本题的栈存放数组元素的下标。
  • 求每一个i左边离i最近且小于a[i]的位置为例:
    1、首先我们从左往右遍历数组。
    2、假设遍历到的元素是a[i],栈顶元素top对应的数组中的元素是a[top],然后我们拿a[i] 和 a[top]进行对比。
    如果a[top] > a[i],就说明top不是第i个元素的解,也不会是i以后任何元素的解(因为i比top距离后面的数更近,同时a[i] < a[top]),所以我们就把top弹出,直到栈为空或者栈顶元素(数组的下标)对应数组中的元素小于a[i]。
    3、如果a[top] < a[i],就说明第i个数的解就是top,因为栈内的元素都是单调递增的,所有top是离i最近的数,即top就是所求值。然后因为i可能是i右侧的候选解,所以把i加入栈中。
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param nums int整型一维数组 
# @return int整型二维数组
#
class Solution:
    def foundMonotoneStack(self , nums: List[int]) -> List[List[int]]:        
        # 1、单调栈:从左到右遍历找l,从右到左遍历找r,
        n=len(nums)
        stack=[]
        res=[]
        lres=[0]*n
        rres=[0]*n
        for i in range(n):
            while stack and nums[stack[-1]] >= nums[i]:
                #若栈顶元素比nums[i]大,淘汰栈顶元素
                #i左边解都找到了,则i和i右侧的都不可能是这些更大的元素
                #一直弹栈,直到栈顶元素小于nums[i]
                stack.pop()
            #若栈空了,说明i左边都比nums[i]大,无解,否则,栈顶就是答案
            lres[i]=stack[-1] if stack else -1
            #i入栈,因为i可能成为i右边的答案
            stack.append(i)
        
        #清空栈
        stack=[]
        
        #从右往左遍历,同逻辑
        for i in range(n-1,-1,-1):
            while stack and nums[stack[-1]] >= nums[i]:
                stack.pop()
            rres[i]=stack[-1] if stack else -1
            #i入栈,因为i可能成为i左边的答案
            stack.append(i)
        
        #合并l和r的结果
        for i in range(n):
            res.append([lres[i],rres[i]])
        return res
    #2、暴力破解,超时
#         n=len(nums)
#         res=[]
#         for i in range(0, n):
#             l=-1
#             r=-1
#             #从左往右找l,比nums[i]小的最近的nums[l]
#             for j in range(0, i):
#                 if nums[j] < nums[i]:
#                     l=j
#             #从右往左找r,比nums[i]小的最近的nums[r]
#             for j in range(n-1,i,-1):
#                 if nums[j] < nums[i]:
#                     r=j
#             res.append([l,r])
#         return res
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值