题目来源:LeetCode221:最大正方形
问题抽象: 在二进制矩阵中寻找全由 '1' 组成的最大正方形区域并返回其面积,需满足以下核心需求:
-
区域定义:
- 正方形需连续相邻(边长为
s的正方形包含s×s个相邻单元格); - 区域内所有元素必须为
'1'(含'0'则无效); - 边界平行于矩阵边缘(非斜向)。
- 正方形需连续相邻(边长为
-
计算目标:
- 输出最大正方形的面积(边长平方),若不存在有效正方形则返回
0; - 需高效处理大规模矩阵(
300×300上限)。
- 输出最大正方形的面积(边长平方),若不存在有效正方形则返回
-
动态规划策略:
- 定义
dp[i][j]表示以(i,j)为右下角的最大正方形边长; - 状态转移:
- 若
matrix[i][j]=='1',则dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1; - 若
matrix[i][j]=='0',则dp[i][j]=0;
- 若
- 全局最大值:
max_edge = max(dp[i][j]),面积= max_edge²。
- 定义
-
边界处理:
- 空矩阵或全
'0'矩阵返回0; - 单行/单列矩阵:最大面积为
1(存在'1'时); - 初始化:首行/首列的
dp值直接为0或1(取决于matrix值)。
- 空矩阵或全
输入:二维字符矩阵 matrix(元素仅 '0' 或 '1',行数 m、列数 n ∈ [0,300])
输出:整数(最大正方形面积,值域 0 至 min(m,n)²)
解题思路
使用动态规划解决此问题,核心思想是通过状态转移方程计算以每个位置 (i, j) 为右下角的最大正方形边长。具体步骤如下:
- 状态定义:
dp[j]表示当前行中以第j个元素为右下角的最大正方形边长。使用一维数组优化空间,避免二维数组的开销。 - 状态转移:
- 如果
matrix[i][j]为'0',则dp[j] = 0(不能构成正方形)。 - 如果
matrix[i][j]为'1',则dp[j]由其左侧、上方和左上方的值决定:
[
dp[j] = \min(dp[j-1], dp[j], pre) + 1
]
其中pre表示上一行中第j-1列的值(即左上角的值)。
- 如果
- 边界处理:
- 第一行直接初始化为对应字符的值(0 或 1)。
- 每行的第一列单独处理(因为左侧无数据)。
- 更新最大边长:在动态规划过程中记录最大边长
maxSide。 - 返回结果:最终结果为
maxSide * maxSide。
代码实现(Java版)🔥点击下载源码
class Solution {
public int maximalSquare(char[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int rows = matrix.length;
int cols = matrix[0].length;
int maxSide = 0;
int[] dp = new int[cols]; // 一维DP数组
// 初始化第一行
for (int j = 0; j < cols; j++) {
dp[j] = matrix[0][j] - '0'; // 字符转数字
if (dp[j] > maxSide) {
maxSide = dp[j]; // 更新最大边长
}
}
// 从第二行开始动态规划
for (int i = 1; i < rows; i++) {
int pre = dp[0]; // 保存上一行第一列的值(作为下一列的左上角)
// 处理当前行第一列
dp[0] = matrix[i][0] == '1' ? 1 : 0;
if (dp[0] > maxSide) {
maxSide = dp[0];
}
// 遍历当前行剩余列
for (int j = 1; j < cols; j++) {
int temp = dp[j]; // 保存上一行当前列的值(用于更新pre)
if (matrix[i][j] == '1') {
// 状态转移:取左、上、左上最小值加1
dp[j] = Math.min(Math.min(dp[j - 1], dp[j]), pre) + 1;
if (dp[j] > maxSide) {
maxSide = dp[j]; // 更新最大边长
}
} else {
dp[j] = 0; // 当前元素为0,无法构成正方形
}
pre = temp; // 更新pre为上一行当前列的值
}
}
return maxSide * maxSide; // 返回最大正方形面积
}
}
代码说明
-
初始化处理:
- 检查矩阵是否为空,直接返回0。
- 初始化
dp数组为第一行的值('0'转0,'1'转1),并记录最大边长maxSide。
-
动态规划核心:
pre变量:保存上一行前一列的值(即左上角的值),用于状态转移。- 第一列处理:每行第一列独立处理(无左侧数据),直接根据字符值设置
dp[0]。 - 状态转移:
- 若当前字符为
'1',取左侧 (dp[j-1])、上方 (dp[j]) 和左上角 (pre) 的最小值加1。 - 若为
'0',则dp[j] = 0。
- 若当前字符为
- 更新
pre:每次迭代保存上一行当前列的值,供下一列使用。
-
结果计算:
- 遍历过程中持续更新
maxSide(最大边长)。 - 返回
maxSide * maxSide(最大正方形面积)。
- 遍历过程中持续更新
提交详情(执行用时、内存消耗)

956

被折叠的 条评论
为什么被折叠?



