一、题目
在一个由'0'和'1'组成的二维矩阵内,找到
只包含'1'的最大正方形
,并返回其面积。
输入 :matrix =[ [" 1 "," 0 "," 1 "," 0 "," 0 "] ,[" 1 "," 0 "," 1 "," 1 "," 1 "] ,[" 1 "," 1 "," 1 "," 1 "," 1 "] ,[" 1 "," 0 "," 0 "," 1 "," 0 "] ]输出 : 4
输入 : m a tri x = [ [" 0 "," 1 "] , [" 1 "," 0 "] ]输出 : 1
示例
3
:
输入 : m a tri x = [ [" 0 "] ]输出 : 0
提示:
m == ma tri x . l ength
n == ma tri x [i]. l ength
1 <= m, n <= 300
ma tri x [i][j] 为 '0' 或 '1'
二、求解思路
题目要求我们找出由数字1构成的最大正方形。最直观的解决方案是采用暴力搜索方法。具体来说,如果某个位置的值为1,我们就将其视为正方形的左上角,然后向右和向下搜索,尝试找到最大的正方形,同时确保该正方形内的所有值均为1。
尽管这种方法易于理解,但编写代码较为复杂,且时间效率较低。因此,我们转向另一种更为高效的解决方案——动态规划。
我们定义一个二维数组dp[m][n],其中dp[i][j]表示以矩阵中坐标(i, j)为右下角的最大正方形的边长。为了求解dp[i][j],我们需要检查矩阵中matrix[i][j]的值。
如果matrix[i][j]为0,则无法构成正方形,因此dp[i][j] = 0。
如果matrix[i][j]为1,表明至少可以构成一个边长为1的正方形。为了找到更大的正方形,我们还需要检查其左上角的值dp[i-1][j-1]。如果dp[i-1][j-1]为0,那么以坐标(i, j)为右下角的最大正方形边长就是1,如下图所示:
如果左上角的值 dp[i -1][j -1] 不是0,也就是说他也可以构成正方形,那么以坐标 (i , j) 为
右下角有可能可以构成一个更大的正方形。为啥说是有可能,因为如果我们要确定他能不
能构成一个更大的正方形,还要往他的上边和左边找
,看看下面的图
有可能是下面这种情况,就是左边或者上边的某一个高度小于 dp[i -1][j -1] 的值,要想构
成最大的正方形我们只能取最小的。
也有可能是下面这种,就是左边和上边的高度都不小于 dp[i -1][j -1] 的值。
所以我们可以得出结论,如果 (i , j) 是1,那么以他为右下角的最大正方形边长是
{dp[i -1][j -1],上边的高度,左边的高度}这3个中最小的+1。
这 里 有 个 问 题 就 是 , 如 果 (i , j) 是 1 , 我 们 有 必 要 往 他 的 上 边 和 左 边 查 找 吗 , 很 明 显 没 必要,上边可以用 dp[i -1][j] 来代表,左边可以用dp[i][j -1]来代表。注意这里 dp[i -1]
[j] 并不是上边为1的高度,dp[i -1][j] 只会小,不会大,可以想一下为什么可以代表。
所以我们可以找出递推公式 :
如果坐标(i,j)为0,
则dp[i][j]=0;
如果坐标(i,j)为1,
则dp[i][j]=min(dp[i -1][j],dp[i][j -1],dp[i -1][j -1])+1;
三、代码实现
c++代码实现如下:
#include <iostream>
#include <vector>
#include <algorithm>
// 声明 maximalSquare 函数
int maximalSquare(std::vector<std::vector<char>>& matrix);
int main() {
// 定义一个二维字符数组(矩阵)
std::vector<std::vector<char>> matrix = {
{'1', '0', '1', '0', '0'},
{'1', '0', '1', '1', '1'},
{'1', '1', '1', '1', '1'},
{'1', '0', '0', '1', '0'}
};
// 调用 maximalSquare 函数并获取结果
int result = maximalSquare(matrix);
// 输出结果
std::cout << "The area of the largest square containing all '1's is: " << result << std::endl;
return 0;
}
// 定义 maximalSquare 函数
int maximalSquare(std::vector<std::vector<char>>& matrix) {
// 二维矩阵的宽和高
int height = matrix.size();
int width = matrix[0].size();
std::vector<std::vector<int>> dp(height + 1, std::vector<int>(width + 1, 0));
int maxSide = 0; // 最大正方形的宽
for (int i = 1; i <= height; i++) {
for (int j = 1; j <= width; j++) {
if (matrix[i - 1][j - 1] == '1') {
// 递推公式
dp[i][j] = std::min({dp[i - 1][j], dp[i - 1][j - 1], dp[i][j - 1]}) + 1;
// 记录最大的边长
maxSide = std::max(maxSide, dp[i][j]);
}
}
}
// 返回正方形的面积
return maxSide * maxSide;
}