221. 最大正方形

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

public int maximalSquare(char[][] matrix) {
if (matrix.length == 0) return 0;
int rows = matrix.length, cols = matrix[0].length;
int maxSide = 0;
int[][] dp = new int[rows + 1][cols + 1];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] == '1') {
dp[i + 1][j + 1] = Math.min(Math.min(dp[i + 1][j], dp[i][j + 1]), dp[i][j]) + 1;
maxSide = Math.max(maxSide, dp[i + 1][j + 1]);
}
}
}
return maxSide * maxSide;
}

状态转移方程的证明:

https://leetcode-cn.com/problems/maximal-square/solution/li-jie-san-zhe-qu-zui-xiao-1-by-lzhlyle/(原文链接)

理解 min(上, 左, 左上) + 1

如题,在其他动态规划方法的题解中,大都会涉及到下列形式的代码:

// 伪代码
if (matrix(i - 1, j - 1) == '1') {
    dp(i, j) = min(dp(i - 1, j), dp(i, j - 1), dp(i - 1, j - 1)) + 1;
}

其中,dp(i, j) 是以 matrix(i - 1, j - 1) 为 右下角 的正方形的最大边长。(感谢 @liweiwei1419 提出补充)
等同于:dp(i + 1, j + 1) 是以 matrix(i, j) 为右下角的正方形的最大边长

翻译成中文

    若某格子值为 1,则以此为右下角的正方形的、最大边长为:上面的正方形、左面的正方形或左上的正方形中,最小的那个,再加上此格。

先来阐述简单共识

    若形成正方形(非单 1),以当前为右下角的视角看,则需要:当前格、上、左、左上都是 1
    可以换个角度:当前格、上、左、左上都不能受 0 的限制,才能成为正方形

 

 上面详解了 三者取最小 的含义:

    图 1:受限于左上的 0
    图 2:受限于上边的 0
    图 3:受限于左边的 0
    数字表示:以此为正方形右下角的最大边长
    黄色表示:格子 ? 作为右下角的正方形区域

就像 木桶的短板理论 那样——附近的最小边长,才与 ? 的最长边长有关。
此时已可得到递推公式
// 伪代码
if (grid[i - 1][j - 1] == '1') {
    dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
}
从感性理解,到代码实现

    从上述图解中,我们似乎得到的只是「动态规划 推进 的过程」,即「如何从前面的 dp 推出后面的 dp」,甚至还只是感性理解
    距离代码我们还缺:dp 具体定义如何,数组多大,初值如何,如何与题目要求的面积相关
    dp 具体定义:dp[i + 1][j + 1] 表示 「以第 i 行、第 j 列为右下角的正方形的最大边长」
        为何不是 dp[i][j]
        回到图解中,任何一个正方形,我们都「依赖」当前格 左、上、左上三个方格的情况
        但第一行的上层已经没有格子,第一列左边已经没有格子,需要做特殊 if 判断来处理
        为了代码简洁,我们 假设补充 了多一行全 '0'、多一列全 '0'

 

     此时 dp 数组的大小也明确为 new dp[height + 1][width + 1]
    初始值就是将第一列 dp[row][0] 、第一行 dp[0][col] 都赋为 0,相当于已经计算了所有的第一行、第一列的 dp 值
    题目要求面积。根据 「面积 = 边长 x 边长」可知,我们只需求出 最大边长 即可
        定义 maxSide 表示最长边长,每次得出一个 dp,就 maxSide = max(maxSide, dp);
        最终返回 return maxSide * maxSide;

参考代码

    时间复杂度 O(height∗width)O(height * width)O(height∗width)
    空间复杂度 O(height∗width)O(height * width)O(height∗width)

 

posted @   zhangshuai2496689659  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示