LeetCode题解:221. 最大正方形,动态规划,JavaScript,详细注释
chencl1986 opened this issue · 0 comments
chencl1986 commented
原题链接:221. 最大正方形
解题思路:
- 假设
matrix[i][j] === ’1‘
,它自己是一个正方形。 - 只有在
matrix[i - 1][j]
、matrix[i][j - 1]
、matrix[i - 1][j - 1]
都为'1'
的时候,才能形成一个更大的正方形。 - 如果用
dp
数组递推,dp[i][j]
代表当前的最大正方形边长,它是由dp[i - 1][j]
、dp[i][j - 1]
、dp[i - 1][j - 1]
的状态递推而来。 - 因此
dp
是一个(m+1)*(n+1)
的矩阵。 matrix[i - 1][j - 1] === '1'
时,dp[i][j]
才可以与之前已知的边长组成新的正方形。由于是正方形,因此只能取之前状态的最小值,否则就成了长方形。- 状态转移方程为:
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1
。当前位置的边长需要记为1。 - 每次递推后,都要记录当前得到的边长最大值
max
,最终返回max ** 2
,即为最大面积。
/**
* @param {character[][]} matrix
* @return {number}
*/
var maximalSquare = function (matrix) {
const m = matrix.length; // 缓存矩阵行数
const n = matrix[0].length; // 缓存矩阵列数
// 创建一个m+1行n+1列的矩阵用于递推
// 由于递推matrix的时候的第一行和第一列,需要判断-1行和-1列的最小值
// 因此初始化dp的第一行和第一列都为0,dp的i行和j列对应的是matrix的i-1行i-1列
// 创建dp时只要存入第一行的值
let dp = [new Array(n + 1).fill(0)];
let max = 0; // 存储遇到的最大正方形边长
// 递推matrix的每个位置,计算每个位置能形成的正方形最大边长
for (let i = 1; i <= m; i++) {
// 每次循环dp中存入当前行的值
dp.push(new Array(n + 1).fill(0));
for (let j = 1; j <= n; j++) {
// 当遇到矩阵值为1时,表示当前存在正方形
if (matrix[i - 1][j - 1] === '1') {
// 计算当前位置能形成的最大正方形边长
dp[i][j] =
// 当前位置是和左、上、左上3个方向形成正方形
// 能形成的最大正方形会受到这3个位置的限制,因此取最小值
Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) +
// 当前位置的自身的边长
1;
// 记录所有边长的最大值
max = Math.max(max, dp[i][j]);
}
}
}
// 最大边长的平方是最大面积
return max ** 2;
};