秋招-算法-最大矩形

67 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情 >>

一、题目描述 LeetCode - 85

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

image.png

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。

示例 2:

输入:matrix = []
输出:0

示例 3:

输入:matrix = [["0"]]
输出:0

示例 4:

输入:matrix = [["1"]]
输出:1

示例 5:

输入:matrix = [["0","0"]]
输出:0

二、解题思路

本题要求返回矩阵中的最大矩形面积,与求“最大正方形”一样,可以考虑使用动态规划来求解。
在构建状态转移方程时,使用dp[i][j]代表在矩阵matrix[i][j]点左边连续1的数量,然后对于矩阵中任意一个点,依次计算以该点为矩形右下角顶点的矩形面积,取最大值即可。在计算面积时需要考虑矩形的宽度,既dp[i][j]应该取较小的值。
注意,在求每个矩形的面积时需要判断矩形的宽度应该取dp数组列的哪个值合适。防止取到无法构成矩形的宽度。

三、代码

class Solution {
    public int maximalRectangle(char[][] matrix) {
        int res = 0;
        int row = matrix.length;
        int col = matrix[0].length;
        int[][] dp = new int[row][col];

        for (int i = 0; i < row; i++) {
            if (matrix[i][0] == '1'){
                dp[i][0] = 1;
            }
            for (int j = 1; j < col; j++) {
                if (matrix[i][j] == '1') {
                    dp[i][j] = dp[i][j - 1] + 1;
                }
            }
        }
        res = 0;
        for (int i=0; i<row; i++){
            for (int j=0; j<col; j++){
                int k = dp[i][j];
                int area = k;
                for(int m=i-1; m>=0; m--){
                    k = Math.min(dp[m][j], k);
                    area = Math.max(area, k * (i+1-m));
                }
                res = Math.max(res, area);
            }
        }
        return res;
    }
}

四、总结

本题使用动态规划求解,解法类似求最大正方形,都是考虑由右下角顶点构成矩形的面积,最后求最大值。时间复杂度为O(m^2*n),空间复杂度为O(mn),其中m为矩阵的行数,n为矩阵的列数。