最大矩形问题

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

 思路:从左到右遍历高度,将高度存入栈中,如果当前高度小于栈顶元素,可计算出该栈顶元素所能取得的最大面积,并将该栈顶元素弹出,继续比较下一个栈顶元素与当前高度,直至栈顶元素小于当前高度。当前元素小于栈顶元素时,直接将该高度入栈。遍历完所有元素后,依次弹出栈顶元素,计算该高度对应的面积。

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        if not heights:
            return 0
        stack = []  # 用来存储高度
        max_val = 0
        for i,h in enumerate(heights):
            if not stack:   # 如果栈为空,将高度入栈
                stack.append([h,i])
                continue
            elif h < stack[-1][0]:  # 如果当前高度小于栈顶元素
                while h < stack[-1][0]:
                    pop_h = stack.pop() # 计算栈顶高度所能取得的最大面积
                    if not stack:   # 如果当前栈中只有一个元素,则该元素的宽为i
                        max_val = max(max_val,i*pop_h[0])
                        break
                    else:   # 如果栈中还有元素,则宽为新栈顶元素的坐标到i
                        max_val = max(max_val,(i-stack[-1][1]-1)*pop_h[0])
            stack.append([h,i])
        while stack:
            pop_h = stack.pop() # 对栈中剩余的高度计算面积
            if stack:
                max_val = max(max_val,(len(heights)-stack[-1][1]-1)*pop_h[0])
                # 当栈中还有元素时,则宽为新栈顶元素的坐标到最后(整个数组的长度)
            else:
                max_val = max(max_val,len(heights)*pop_h[0])
                # 当栈中没有元素时,说明该高度为整个数组中的最小值。则宽为整个数组的长度
        return max_val

2. 矩阵中的最大矩形:给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

 思路:该问题可转换为问题1,从上到下遍历矩阵的每一行,这样便可以利用问题1求解。如由上述矩阵可得到4个高度分别为:[1,0,1,0,0]、[2,0,2,1,1]、[3,1,3,2,3]、[4,0,0,3,0]的问题1。

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        def largestRectangleArea(heights):
            if not heights:
                return 0
            stack = []  # 用来存储高度
            max_val = 0
            for i,h in enumerate(heights):
                if not stack:   # 如果栈为空,将高度入栈
                    stack.append([h,i])
                    continue
                elif h < stack[-1][0]:  # 如果当前高度小于栈顶元素
                    while h < stack[-1][0]:
                        pop_h = stack.pop() # 计算栈顶高度所能取得的最大面积
                        if not stack:   # 如果当前栈中只有一个元素,则该元素的宽为i
                            max_val = max(max_val,i*pop_h[0])
                            break
                        else:   # 如果栈中还有元素,则宽为新栈顶元素的坐标到i
                            max_val = max(max_val,(i-stack[-1][1]-1)*pop_h[0])
                stack.append([h,i])
            while stack:
                pop_h = stack.pop() # 对栈中剩余的高度计算面积
                if stack:
                    max_val = max(max_val,(len(heights)-stack[-1][1]-1)*pop_h[0])
                    # 当栈中还有元素时,则宽为新栈顶元素的坐标到最后(整个数组的长度)
                else:
                    max_val = max(max_val,len(heights)*pop_h[0])
                    # 当栈中没有元素时,说明该高度为整个数组中的最小值。则宽为整个数组的长度
            return max_val

        if not matrix:
            return 0
        res = 0
        heights = [0] * len(matrix[0])
        for row in matrix:
            for i,v in enumerate(row):
                if v == '1':
                    heights[i] += int(v)
                else:
                    heights[i] = 0
            ans = largestRectangleArea(heights)
            res = max(res,ans)
        return res

3. 矩阵中的最大正方形:在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。

思路:利用动态规划的思想,如果矩阵中该位置的值为1,则该位置所能求得的最大正方形边长为:min(左上,左,上) + 1。如果矩阵中该位置的值为0,则该位置所能求得的最大正方形边长即为0。

class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        n = len(matrix)
        m = len(matrix[0])
        res = 0
        dp_table = [[0 for _ in range(m)] for _ in range(n)]
        for i in range(n):
            for j in range(m):
                if matrix[i][j] == '1':
                    if (i-1) >= 0 and (j-1) >= 0 and dp_table[i-1][j-1]:
                        dp_table[i][j] = \
                        min(dp_table[i-1][j-1],dp_table[i-1][j],dp_table[i][j-1]) + 1
                    else:
                        dp_table[i][j] = 1
                    res = max(res,dp_table[i][j])
                else:
                    pass
        return res**2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值