单调栈python总结_leetcode

什么时候用到?

一维数组,寻找任何一个元素左边或者右边第一个比自己大或者校的元素,时间复杂度为O(n)

说明:
单调递增栈,从栈口到栈底的位置,元素呈现单调增的排列顺序
单调递减栈,从栈口到栈底的位置,元素呈现单调减的排列顺序

单调栈实际上也就是用空间换时间,用栈记录遍历过的元素下标;

一寻找右边第一个大的元素

从左向右维护一个单调递增栈,遍历每个元素和栈口的元素进行比较;

def dailyTemperatures(temperatures):
    stack = [0]#从左向右遍历,记录一下数组第一个下标索引
    answer = [0] * len(temperatures)
    for i in range(1, len(temperatures)):
        if temperatures[i] < temperatures[stack[-1]]:
        #当前遍历的元素小于栈口的元素,可以直接加入构成一个单调增的序列
            stack.append(i)
        elif temperatures[i] == temperatures[stack[-1]]:
        #当前遍历的元素等于栈口的元素,因为目标是要寻找右边第一个大的元素,不是大于等于的元素,所以添加到当前序列,用在后面当遇到大的元素时作差
            stack.append(i)
        else:
            while stack and temperatures[i] > temperatures[stack[-1]]:
            #如果当前遍历的元素比当前栈口索引的元素大时,直接添加则栈不能构成单调增的形式,所以需要拿出来比较并pop
            #遍历的元素比栈口元素大,在原数组序列中也就意味着是该元素后面第一大的元素了,然后将两者的索引进行作差即可;
                answer[stack[-1]] = i - stack[-1]
                stack.pop()
            stack.append(i)
    return answer
temp = [73,74,75,71,69,72,76,73]
res = dailyTemperatures(temp)
print(res)
#res = [1, 1, 4, 2, 1, 1, 0, 0]

二寻找右边第一个小的元素

从左向右维护一个单调递减栈,遍历每个元素和栈口的元素进行比较;

# #寻找右边第一个小的元素
def dailyTemperatures(temperatures):
    stack = [0]
    answer = [0] * len(temperatures)
    for i in range(1, len(temperatures)):
        if temperatures[i] > temperatures[stack[-1]]:#只是在维护栈的时候注意比较对象即可
            stack.append(i)
        elif temperatures[i] == temperatures[stack[-1]]:
            stack.append(i)
        else:
            while stack and temperatures[i] < temperatures[stack[-1]]:#只是在维护栈的时候注意比较对象即可
                answer[stack[-1]] = i - stack[-1]
                stack.pop()
            stack.append(i)
    return answer
    
 temp_1 = [73,74,75,71,69,72,76,73]
 res = dailyTemperatures(temp_1)
 print(res)
 #[3, 2, 1, 1, 0, 0, 1, 0]

三寻找左边第一个大的元素

倒序维护一个单调递增栈,遍历每个元素和栈口的元素进行比较;

def dailyTemperatures(temperatures):
    stack = [len(temperatures) - 1]#倒序遍历,所以需要先加入当前数组的最后一个索引
    answer = [0] * len(temperatures)
    for i in range(len(temperatures) - 2, -1, -1):#倒序遍历
        if temperatures[i] < temperatures[stack[-1]]:
            stack.append(i)
        elif temperatures[i] == temperatures[stack[-1]]:
            stack.append(i)
        else:
            while stack and temperatures[i] > temperatures[stack[-1]]:
                answer[stack[-1]] = i - stack[-1]
                #answer[stack[-1]] = stack[-1] - i
                stack.pop()
            stack.append(i)
    return answer

temp_1 = [73,74,75,71,69,72,76,73]
res = dailyTemperatures(temp_1)
print(res)
#[0, 0, 0, -1, -1, -3, 0, -1]负数表示和前一个索引的差值

#answer[stack[-1]] = stack[-1] - i运行的结果为正数,[0, 0, 0, 1, 1, 3, 0, 1]

四寻找左边第一个小的元素

倒序维护一个单调递减栈,遍历每个元素和栈口的元素进行比较;

def dailyTemperatures(temperatures):
    stack = [len(temperatures) - 1]
    answer = [0] * len(temperatures)
    for i in range(len(temperatures) - 2, -1, -1):
        if temperatures[i] > temperatures[stack[-1]]:
            stack.append(i)
        elif temperatures[i] == temperatures[stack[-1]]:
            stack.append(i)
        else:
            while stack and temperatures[i] < temperatures[stack[-1]]:
                answer[stack[-1]] = i - stack[-1] 
                #answer[stack[-1]] = stack[-1] - i
                stack.pop()
            stack.append(i)
    return answer
temp_1 = [73,74,75,71,69,72,76,73]
res = dailyTemperatures(temp_1)
print(res)
#[0, -1, -1, 0, 0, -1, -1, -2]
#answer[stack[-1]] = stack[-1] - i:输出相应的正数间隔[0, 1, 1, 0, 0, 1, 1, 2]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值