【leetcode】单调栈刷题tricks

什么时候用单调栈?

通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了,时间复杂度为O(n)。

单调栈作用:就是用一个栈来记录我们遍历过的元素

单调栈存放的内容:单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接通过索引就可以获取。

如果求一个元素右边第一个更大元素,单调栈就是递增的(从栈头到栈底的顺序),如果求一个元素右边第一个更小元素,单调栈就是递减的(从栈头到栈底的顺序)。

LeetCode739题 每日温度

class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        res = [0] * len(temperatures)
        stack = []
        for i in range(len(temperatures)):
            # 若当前温度高于栈顶元素,则持续出栈,进行结果更新,栈顶到栈底是递增的
            while stack and temperatures[i] > temperatures[stack[-1]]:
                res[stack[-1]] = i - stack[-1]
                stack.pop()
            # 将当前温度入栈
            stack.append(i)
        return res

LeetCode496题 下一个更大元素 

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        res = [-1] * len(nums1)
        # nums1元素值-索引映射
        d = dict()
        for i in range(len(nums1)):
            d[nums1[i]] = i
        stack = []
        for i in range(len(nums2)):
            while stack and nums2[i] > nums2[stack[-1]]:
                res[d[nums2[stack[-1]]]] = nums2[i]
                stack.pop()
            # nums1中元素才会入栈
            if nums2[i] in d:
                stack.append(i)
        return res

 LeetCode503题 下一个更大元素II

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        res = [-1] * len(nums)
        stack = []
        for i in range(len(nums)):
            while stack and nums[i] > nums[stack[-1]]:
                res[stack[-1]] = nums[i]
                stack.pop()
            stack.append(i)
        for i in range(len(nums)):
            while stack and nums[i] > nums[stack[-1]]:
                res[stack[-1]] = nums[i]
                stack.pop()
            # 第二次遍历不需要将元素i入栈
            # 因为第一次遍历后不在栈中的元素已经找到了答案
        return res

LeetCode42题 接雨水

本质在找每个元素左右两边第一个比它大的元素

class Solution:
    def trap(self, height: List[int]) -> int:
        res = 0
        stack = []
        for i in range(len(height)):
            while stack and height[i] > height[stack[-1]]:
                # 此时对于索引stack[-1],右边第一个比它大的位置为i,左边第一个比它大的位置为stack[-2]
                if len(stack) > 1:
                    # 以stack[-1]为底的水池高度
                    h = min(height[i], height[stack[-2]]) - height[stack[-1]]
                    # 以stack[-1]为底的水池宽度
                    w = i - stack[-2] - 1
                    res += h * w
                stack.pop()
            stack.append(i)
        return res

 LeetCode84题 柱状图中最大的矩形

本质在找每个元素左右两边第一个比它小的元素

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        res = 0
        # heights两边加0元素,可以解决不包含边界元素问题
        heights = [0] + heights + [0]
        stack = []
        for i in range(len(heights)):
            while stack and heights[i] < heights[stack[-1]]:
                if len(stack) > 1:
                    # 计算以heights[stack[-1]]为高的矩形的最大面积
                    # 主要在寻找heights[stack[-1]]左右两边的第一个比它小的元素
                    tmp = (i - stack[-2] - 1) * heights[stack[-1]]
                    res = max(res, tmp)
                stack.pop()
            stack.append(i)
        return res

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值