单调栈-递增

本文详细介绍了如何使用单调栈解决数组中寻找每个位置左侧和右侧最小值的问题。通过从左到右和从右到左遍历数组,维护一个单调栈,确保栈内元素始终是单调递增的。当遇到大于栈顶元素的值时,弹出栈顶元素,直至找到符合条件的解。这种方法避免了暴力搜索,提高了效率。
摘要由CSDN通过智能技术生成

单调栈-牛客

思路

  • 单调栈
    单调栈是指栈内元素是具有有单调性的栈,单调栈在入栈的时候,需要将待入栈的元素和栈顶元素进行对比,看待加入栈的元素入栈后是否会破坏栈的单调性,如果不会,直接入栈;否则一直弹出到满足条件为止。
    本题的栈存放数组元素的下标。
  • 求每一个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
    评论
Python中,单调栈单调队列是两种不同的数据结构。单调栈是一个,它的特点是内的元素是单调的,可以是递增或递减的。在构建单调栈时,元素的插入和弹出都是在的一端进行的。与此类似,单调队列也是一个队列,它的特点是队列内的元素是单调的,可以是递增或递减的。在构建单调队列时,元素的插入是在队列的一端进行的,而弹出则是选择队列头进行的。 单调队列在解决某些问题时,能够提升效率。例如,滑动窗口最大值问题可以通过使用单调队列来解决。单调队列的结构可以通过以下代码来实现: ```python class MQueue: def __init__(self): self.queue = [] def push(self, value): while self.queue and self.queue[-1 < value: self.queue.pop(-1) self.queue.append(value) def pop(self): if self.queue: return self.queue.pop(0) ``` 上述代码定义了一个名为MQueue的类,它包含一个列表作为队列的存储结构。该类有两个方法,push和pop。push方法用于向队列中插入元素,它会删除队列尾部小于插入元素的所有元素,并将插入元素添加到队列尾部。pop方法用于弹出队列的头部元素。 总结来说,单调栈单调队列都是为了解决特定问题而设计的数据结构。单调栈在构建时元素的插入和弹出都是在的一端进行的,而单调队列则是在队列的一端进行的。在Python中,可以通过自定义类来实现单调队列的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值