珍宝鸭的力扣练习(15):单调栈/队方法解题合集

要知道单调栈的适用于解决什么样的问题,我们首先需要知道单调栈的作用。
单调栈分为单调递增栈和单调递减栈,
通过使用单调栈我们可以访问到最近的比他大(小)的元素。也就是说在队列或数组中,我们需要通过比较前后元素的大小关系来解决问题时我们通常使用单调栈。

题目1:直方图中的最大面积

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述

题解:首先我们枚举某一根柱子 i 作为高 h=heights[i];
随后我们需要进行向左右两边扩展,使得扩展到的柱子的高度均不小于 h。换句话说,我们需要找到左右两侧最近的高度小于 h 的柱子,这样这两根柱子之间(不包括其本身)的所有柱子高度均不小于 h,并且就是 i能够扩展到的最远范围。

在这里插入图片描述

class Solution:
    def largestRectangleArea(self, heights):
        n = len(heights)
        left, right = [0] * n, [0] * n

        mono_stack =[]
        for i in range(n):
            while mono_stack and heights[mono_stack[-1]] >= heights[i]:
                mono_stack.pop()
            left[i] = mono_stack[-1] if mono_stack else -1
            mono_stack.append(i)
        
        mono_stack = list()
        for i in range(n - 1, -1, -1):
            while mono_stack and heights[mono_stack[-1]] >= heights[i]:
                mono_stack.pop()
            right[i] = mono_stack[-1] if mono_stack else n
            mono_stack.append(i)
        
        ans = max((right[i] - left[i] - 1) * heights[i] for i in range(n)) if n > 0 else 0
        return ans

题目2:矩阵中的最大矩形

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
在这里插入图片描述
题解:我们首先计算出矩阵的每个元素的左边连续 1的数量,使用二维数组 记录,其中 help[i][j]为矩阵第 i 行第 j 列元素的左边连续 1 的数量。
在这里插入图片描述
如图中所示,阴影部分的面积即为第二行最后一列,高度为3的矩阵,向左拓展一格的面积。这么思考的话,每一列就是第一题中的直方图。对于每一个直方图,寻找相邻的最近的高度小于其的格子。

class Solution(object):
    def maximalRectangle(self, matrix):
        if not matrix: return 0
        m,n=len(matrix),len(matrix[0])
        help=[[0 for _ in range(n)] for _ in range(m)]
        for i in range(m):#构造help矩阵
            count=0
            for j in range(n):
                if matrix[i][j]=="1":
                    count+=1
                else:
                    count=0
                help[i][j]=count
        left_all= []
        right_all=[]
        for j in range(n):#每一列为直方图的横轴
            left=[0 for i in range(m)]
            stack=[]
            for i in range(m):
                while stack and help[stack[-1]][j]>=help[i][j]:
                    stack.pop()
                if stack:
                    left[i] = stack[-1]
                else :left[i] =-1
                stack.append(i)
            left_all.append(left)

        for j in range(n):#每一列为直方图的横轴
            right=[0 for i in range(m)]
            stack=[]
            for i in range(m-1,-1,-1):
                while stack and help[stack[-1]][j] >= help[i][j]:
                    stack.pop()
                if stack:
                    right[i] = stack[-1]
                else:
                    right[i] = m
                stack.append(i)
            right_all.append(right)

        result=0
        for j in range(n):  # 每一列为直方图的横轴
            for i in range(m):
                result=max(result,(right_all[j][i]-left_all[j][i]-1)*help[i][j])
        return  result

题目3:滑动窗口的最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

题解:将单调栈优化最大堆问题中的此题。

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        n = len(nums)
        stack=[]
        for i in range(k):
            while stack and nums[stack[-1]]<=nums[i]:
                stack.pop()
            stack.append(i)
        ans = [nums[stack[0]]]
        for i in range(k, n):
            while stack and nums[i] >= nums[stack[-1]]:
                stack.pop()
            stack.append(i)
            while stack[0] <= i - k:
                stack.pop(0)
            ans.append(nums[stack[0]])
        return ans

获取队列的最大值

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

class MaxQueue(object):

    def __init__(self):
        self.q=[]
        self.p=[]


    def max_value(self):
        """
        :rtype: int
        """
        return -1 if not self.p else self.p[0]


    def push_back(self, value):
        """
        :type value: int
        :rtype: None
        """
     
        while self.p and self.p[-1]<value:
            self.p.pop()
        self.p.append(value)
        self.q.append(value)



    def pop_front(self):
        """
        :rtype: int
        """
        if not self.q: return -1
        if  self.q[0]==self.p[0]:
            self.p.pop(0) 
        return  self.q.pop(0) 



# Your MaxQueue object will be instantiated and called as such:
# obj = MaxQueue()
# param_1 = obj.max_value()
# obj.push_back(value)
# param_3 = obj.pop_front()
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值