夯实算法-最大正方形

245 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的29天,点击查看活动详情

题目:LeetCode

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

示例 1:

max1grid.jpg

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

示例 2:

max2grid.jpg

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

示例 3:

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

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 300
  • matrix[i][j] 为 '0' 或 '1'

解题思路

取矩阵行数为 m,列数为 n,行索引i,从0 到 m−1,列索引从 0 到n−1

遍历矩阵,对于每个为'1'的元素,以它为左上角,来搜索最大的正方形,遍历完成后即能找到最大的正方形。

为了方便,返回正方形的边长,这是为了方便做剪枝,如果边长大于最小边(即m和n)的一半,那么当前找到的正方形一定是全局最大的,不可有比它再大的了,所以可以停止遍历了。

具体说下搜索最大正方形的过程:以[i,j]为左上角,向左下去搜索,那么最大的可能的边长就是min(m−i,n−j)−1了,记为maxLen。可能的边长len,从1开始增长到maxLen,然后检查外面增加一行和一列是否全是'1',如果是,len就加1,直到遇到有'0'或者到达maxLen为止。如此便能找到以[i,j]为左上的最大正方形,边长即是len。

暂时没有想到,优化方法,想着可能像DFS那样,把搜索过的地方做个标记,这样可以重复查找,但这有问题,因为正方形可能会有重叠,这会导致后面的正方形面积缩小。

代码实现

private int m;
private int n;

public int maximalSquare(char[][] matrix) {
    m = matrix.length;
    n = matrix[0].length;
    int maxArea = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (matrix[i][j] == '1') {
                int len = calcArea(matrix, i, j);
                maxArea = Math.max(len * len, maxArea);
                if (len > (Math.min(m, n) / 2 + 1)) {
                    return maxArea;
                }
            }
        }
    }

    return maxArea;
}

private int calcArea(char[][] matrix, int i, int j) {
    int maxLen = Math.min(m - i, n - j) - 1;
    int len = 1;
    for (; len <= maxLen; len++) {
        boolean allOne = true;
        for (int x = i; x <= i + len; x++) {
            if (matrix[x][j + len] == '0') {
                allOne = false;
                break;
            }
        }
        if (allOne) {
            for (int y = j; y <= j + len; y++) {
                if (matrix[i + len][y] == '0') {
                    allOne = false;
                    break;
                }
            }
        }
        if (!allOne) {
            break;
        }
    }
    return len;
}

运行结果

Snipaste_2022-12-27_18-28-51.png

复杂度分析

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(m2n2)O(m^2n^2)

掘金(JUEJIN)  一起分享知识, Keep Learning!