【问题描述】[第221题][最大正方形][中等]
在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大/长方形正方形,并返回其面积。示例:输入: 1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
长方形 输出: 6
正方形 输出: 4
【解答思路】
1. 长方形 暴力
时间复杂度:O(N^2) 空间复杂度:O(N^2)
public int maximalRectangle(char[][] matrix) {if (matrix.length == 0) {return 0;}//保存以当前数字结尾的连续 1 的个数int[][] width = new int[matrix.length][matrix[0].length];int maxArea = 0;//遍历每一行for (int row = 0; row < matrix.length; row++) {for (int col = 0; col < matrix[0].length; col++) {//更新 widthif (matrix[row][col] == '1') {if (col == 0) {width[row][col] = 1;} else {width[row][col] = width[row][col - 1] + 1;}} else {width[row][col] = 0;}//记录所有行中最小的数int minWidth = width[row][col];//向上扩展行for (int up_row = row; up_row >= 0; up_row--) {int height = row - up_row + 1;//找最小的数作为矩阵的宽minWidth = Math.min(minWidth, width[up_row][col]);//更新面积maxArea = Math.max(maxArea, height * minWidth);}}}return maxArea;
}
2. 正方形 暴力
- 正方形的面积是边长乘边长, maxArea 是没有意义的-- 只记录最大边长即可。然后是其它细节的修改,让代码更简洁,代码如下。
时间复杂度:O(N^2) 空间复杂度:O(N^2)
public int maximalSquare(char[][] matrix) {if (matrix.length == 0) {return 0;}// 保存以当前数字结尾的连续 1 的个数int[][] width = new int[matrix.length][matrix[0].length];// 记录最大边长int maxSide = 0;// 遍历每一行for (int row = 0; row < matrix.length; row++) {for (int col = 0; col < matrix[0].length; col++) {// 更新 widthif (matrix[row][col] == '1') {if (col == 0) {width[row][col] = 1;} else {width[row][col] = width[row][col - 1] + 1;}} else {width[row][col] = 0;}// 当前点作为正方形的右下角进行扩展int curWidth = width[row][col];// 向上扩展行for (int up_row = row; up_row >= 0; up_row--) {int height = row - up_row + 1;if (width[up_row][col] <= maxSide || height > curWidth) {break;}maxSide = Math.max(height, maxSide);}}}return maxSide * maxSide;
}
2. 正方形 动态规划
第 1 步:设计状态
dp[i][j] 表示以 matrix[i][j] 为右下角正方形的最大边长
第 2 步:状态转移方程
dp[i][j] = Min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]) + 1
当前点的左边,上边,左上角的三个点中选一个最小值,然后加 1
第 3 步:考虑初始化
第一行和第一列的 dp[i][j] = matrix[i][j] - ‘0’,也就意味着 dp[i][j] 要么是 0 要么是 1
第 4 步:考虑输出
第 5 步:考虑是否可以状态压缩
时间复杂度:O(N^2) 空间复杂度:O(N)
public int maximalSquare(char[][] matrix) {int rows = matrix.length;if (rows == 0) {return 0;}int cols = matrix[0].length;int[][] dp = new int[rows + 1][cols + 1];int maxSide = 0;for (int i = 1; i <= rows; i++) {for (int j = 1; j <= cols; j++) {//因为多申请了一行一列,所以这里下标要减 1if (matrix[i - 1][j - 1] == '0') {dp[i][j] = 0;} else {dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;maxSide = Math.max(dp[i][j], maxSide);}}}return maxSide * maxSide;
}
【总结】
1.动态规划流程
第 1 步:设计状态
第 2 步:状态转移方程
第 3 步:考虑初始化
第 4 步:考虑输出
第 5 步:考虑是否可以状态压缩
- 二维数组 -> 一维数组
2. 行 row 列 col 注意边界!
- 二维数组
int rows = matrix.length;
nt cols = matrix[0].length;
3. 暴力 ->优化
转载链接:https://leetcode-cn.com/problems/maximal-square/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by–46/
参考链接:https://leetcode-cn.com/problems/maximal-square/solution/li-jie-san-zhe-qu-zui-xiao-1-by-lzhlyle/