题目描述
解题思路
暴力法
由于正方形的面积等于边长的平方,因此要找到最大正方形的面积,首先需要找到最大正方形的边长,然后计算最大边长的平方即可。
暴力法是最简单直观的做法,具体做法如下:
遍历矩阵中的每个元素,每次遇到 11,则将该元素作为正方形的左上角;
确定正方形的左上角后,根据左上角所在的行和列计算可能的最大正方形的边长(正方形的范围不能超出矩阵的行数和列数),在该边长范围内寻找只包含 1 的最大正方形;
每次在下方新增一行以及在右方新增一列,判断新增的行和列是否满足所有元素都是 1。
// 暴力法public int maximalSquare(char[][] matrix) {int maxSide = 0;if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {return maxSide;}for (int i = 0; i < matrix.length; i++) {for (int j = 0; j < matrix[0].length; j++) {if (matrix[i][j] == '1') {// 将1作为左上角,开始搜索正方形maxSide = Math.max(maxSide, 1);// 计算可能搜索的最大边界,防止越界int maxLength = Math.min(matrix.length - i, matrix[0].length - j);for (int k = 0; k < maxLength; k++) {// 表示现在是否符合正方形// 判断新增的一行一列是否均为 1boolean flag = true;// 对角不为1,不需要搜索了if (matrix[i + k][j + k] == '0') break;for (int l = 0; l < k; l++) {if (matrix[i + l][j + k] == '0' || matrix[i + k][j + l] == '0') {// 不满足设置标志为falseflag = false;break;}}if (flag) {// 更新最大边maxSide = Math.max(k + 1, maxSide);} else break;}}}}return maxSide * maxSide;}
dp
先来阐述简单共识
- 若形成正方形(非单 1),以当前为右下角的视角看,则需要:当前格、上、左、左上都是 1
 - 可以换个角度:当前格、上、左、左上都不能受 0 的限制,才能成为正方形
 

这张图直接展示了当前位置的正方形边长和上,左,左上的关系,也就是取最小的加一。
dp表示的是边长,不是面积,表示面积很难求和这三者的关系。
public int maximalSquare(char[][] matrix) {int maxSide = 0;if (matrix.length == 0 || matrix[0].length == 0 || matrix == null) return maxSide;// dp[i]表示:当前以i为矩形的最大边长int[][] dp = new int[matrix.length + 1][matrix[0].length + 1];// 初始化都为0for (int i = 1; i <= matrix.length; i++) {for (int j = 1; j <= matrix[0].length; j++) {if (matrix[i - 1][j - 1] == '1') {// 三者取最大dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;maxSide = Math.max(maxSide, dp[i][j]);}}}return maxSide * maxSide;}

优化
// 优化public int maximalSquare(char[][] matrix) {int maxSide = 0;if (matrix.length == 0 || matrix[0].length == 0 || matrix == null) return maxSide;// dp[i]表示:当前以i为矩形的最大边长int[] dp = new int[matrix[0].length + 1];// 初始化都为0for (int i = 1; i <= matrix.length; i++) {int northwest = 0;for (int j = 1; j <= matrix[0].length; j++) {int nextNorthwest = dp[j];if (matrix[i - 1][j - 1] == '1') {// 三者取最大dp[j] = Math.min(dp[j], Math.min(dp[j - 1], northwest)) + 1;maxSide = Math.max(maxSide, dp[j]);}else dp[j] = 0;northwest = nextNorthwest;}}return maxSide * maxSide;}

