给定一个由 '0' 和 '1' 组成的2维矩阵,返回该矩阵中最大的由 '1' 组成的正方形的面积。输入的矩阵是字符形式而非数字形式。
数据范围:矩阵的长宽满足
,矩阵中的元素属于 {'1','0'}
进阶:空间复杂度
, 时间复杂度
[[1,0,1,0,0],[1,0,1,1,1],[1,1,1,1,1],[1,0,0,1,0]]
4
[[1,0,0],[0,0,0],[0,0,0]]
1
import java.util.*;
public class Solution {
/**
* 最大正方形
* @param matrix char字符型二维数组
* @return int整型
*/
public int solve (char[][] matrix) {
// write code here
int [][]dp = new int[matrix.length][matrix[0].length];
int bc = 0;
dp[0][0]=0;
for(int i=0;i<dp.length;i++){
dp[i][0]=matrix[i][0]-'0';
}
for(int j=0;j<dp[0].length;j++){
dp[0][j]=matrix[0][j]-'0';
}
for(int i=1;i<dp.length;i++){
for(int j=1;j<dp[0].length;j++){
if(matrix[i][j]=='0'){
dp[i][j]=0;
}else{
int up = dp[i-1][j];
int left = dp[i][j-1];
int ul = dp[i-1][j-1];
if(up==left && up==ul){
dp[i][j]=up+1;
}else{
int m = Math.min(up,Math.min(left,ul));
dp[i][j]=m+1;
}
}
}
}
for(int i=0;i<dp.length;i++){
for(int j=0;j<dp[0].length;j++){
bc = Math.max(bc,dp[i][j]);
}
}
int area = bc*bc;
return area;
}
} 前排提示:这道题有个很坑的地方,java输入的matrix是字符型。自测的时候算出来面积两千多,一直不知道啥问题,一看函数参数列表......
/**
* 最大正方形
* @param matrix char字符型二维数组
* @param matrixRowLen int matrix数组行数
* @param matrixColLen int* matrix数组列数
* @return int整型
*/
int min(int a, int b)
{
return a < b ? a : b;
}
int max(int a, int b)
{
return a > b ? a : b;
}
int solve(char** matrix, int matrixRowLen, int* matrixColLen ) {
if (matrixRowLen == 0 || matrixColLen == 0) {
return 0;
}
int res = 0;
for (int i = 0; i < matrixRowLen; i++) {
for (int j = 0; j < *matrixColLen; j++) {
if (matrix[i][j] == '1' && i > 0 && j > 0) {
matrix[i][j] = 1 + min(min(matrix[i-1][j-1], matrix[i-1][j]), matrix[i][j-1]);
res = max(res, (matrix[i][j] - '0'));
}
}
}
return res * res;
} import java.util.*;
//https://www.nowcoder.com/practice/0058c4092cec44c2975e38223f10470e?tpId=117&&tqId=37832&rp=1&ru=/activity/oj&qru=/ta/job-code-high/question-ranking
public class Solution {
/**
* 最大正方形
* @param matrix char字符型二维数组
* @return int整型
*/
public int solve (char[][] matrix) {
//二维矩阵的宽和高
int height = matrix.length;
int width = matrix[0].length;
int[][] dp = new int[height + 1][width + 1];
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] = Math.min(dp[i - 1][j], Math.min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
//记录最大的边长
maxSide = Math.max(maxSide, dp[i][j]);
}
}
}
//返回正方形的面积
return maxSide * maxSide;
}
} int getSquareArea(vector<int> &v, int k) {
if (v.size() < k) return 0;
int count = 0;
for (int i = 0; i < v.size(); ++i) {
if (v[i] != k) count = 0;
else ++count;
if (count == k) return k * k;
}
return 0;
}
# # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # 最大正方形 # @param matrix char字符型二维数组 # @return int整型 # class Solution: def solve(self , matrix: List[List[str]]) -> int: if not matrix: return 0 m, n = len(matrix), len(matrix[0]) f = [[0]*(n+1) for _ in range(m+1)] res = 0 for i in range(1,m+1): for j in range(1,n+1): if matrix[i-1][j-1]=='1': f[i][j] = min(f[i-1][j-1], f[i-1][j], f[i][j-1])+1 res = max(res, f[i][j]) return res*res
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 最大正方形
* @param matrix char字符型二维数组
* @return int整型
*/
public int solve (char[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int rows = matrix.length;
int cols = matrix[0].length;
int[][] dp = new int[rows][cols];
int maxSide = 0;
// 初始化第一行和第一列
for (int i = 0; i < rows; i++) {
if(matrix[i][0] == '1')
dp[i][0] = 1;
}
for (int j = 0; j < cols; j++) {
if(matrix[0][j] == '1')
dp[0][j] = 1;
}
// 动态规划填充dp数组
for (int i = 1; i < rows; i++) {
for (int j = 1; j < cols; j++) {
if (matrix[i][j] == '1') {
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
maxSide = Math.max(maxSide, dp[i][j]);
}
}
}
return maxSide * maxSide;
}
} # # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # 最大正方形 # @param matrix char字符型二维数组 # @return int整型 # class Solution: def solve(self , matrix: List[List[str]]) -> int: # write code here if len(matrix) == 0: return 0 if len(matrix[0]) == 0: return 0 res = 0 dp = [[0 for i in range(len(matrix[0]))] for j in range(len(matrix))] for i in range(len(matrix[0])): if matrix[0][i] == '1': dp[0][i] = 1 for j in range(len(matrix)): if matrix[j][0] == '1': dp[j][0] = 1 for i in range(len(matrix)): for j in range(len(matrix[0])): if matrix[i][j] == '1': dp[i][j] = 1 min_len = min(dp[i-1][j], dp[i][j-1]) if matrix[i-min_len][j-min_len] == '1': dp[i][j] += min_len else: dp[i][j] += min_len-1 for i in range(len(matrix)): for j in range(len(matrix[0])): res = max(res, dp[i][j]) return res*res
// 一眼以为是最大矩形。。反正基本一样思路
class Solution {
public:
/**
* 最大正方形
* @param matrix char字符型vector<vector<>>
* @return int整型
*/
int solve(vector<vector<char> >& matrix) {
// write code here
if(!matrix.size()||!matrix[0].size()) return 0;
vector<vector<int>> dp(matrix.size(),vector<int>(matrix[0].size(),0));
for(int i = 0;i<matrix.size();++i) dp[i][0] = matrix[i][0]=='1'? 1:0;
for(int i = 0;i<matrix.size();++i){
for(int j = 1;j<matrix[0].size();++j){
if(matrix[i][j]=='1') dp[i][j] = dp[i][j-1]+1;
}
}
int res = 1;
for(int i = 0;i<matrix.size();++i){
for(int j = 0;j<matrix[0].size();++j){
if(dp[i][j]>0){
int dx = dp[i][j];int dy= 1;
int x,y; x = j, y= i-1;
while(y>=0&&dp[y][x]>0){
dy++;
dx = min(dx,dp[y][x]);
//确定是不是正方形
if(dx==dy) res = max(res, dx*dy);
y--;
}
}
}
}
return res;
}
};
class Solution {
public:
int solve(vector<vector<char> >& matrix) {
// corner case
if (matrix.empty()) return 0;
const size_t m = matrix.size(), n = matrix[0].size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
int ans = 0;
for (int y = 1; y <= m; ++y)
for (int x = 1; x <= n; ++x)
if (matrix[y - 1][x - 1] == '1') {
// 核心:状态转移方程
dp[y][x] = 1 + min({dp[y - 1][x], dp[y][x - 1], dp[y - 1][x - 1]});
ans = max(ans, dp[y][x]);
}
return ans * ans;
}
}; class Solution: def solve(self , matrix: List[List[str]]) -> int: # write code here if not matrix: return 0 n=len(matrix[0]) m=len(matrix) max_len=0 dp=[[0]*(n+1) for _ in range(m+1)] for i in range(1,m+1): for j in range(1,n+1): if matrix[i-1][j-1]=='1': dp[i][j]=min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1 max_len=max(max_len,dp[i][j]) return max_len*max_len
import java.util.*;
public class Solution {
/**
* 最大正方形
* @param matrix char字符型二维数组
* @return int整型
*/
public int solve (char
[][] matrix) {
// write code here
int
[][]dp = new int
[matrix.length][matrix[0].length];
int bc = 0;
dp
[0][0]=0;
for(int i=0;i<dp.length;i++){
dp
[i][0]=matrix
[i][0]-'0';
}
for(int j=0;j<dp
[0].length;j++){
dp
[0][j]=matrix
[0][j]-'0';
}
for(int i=1;i<dp.length;i++){
for(int j=1;j<dp
[0].length;j++){
if(matrix
[i][j]=='0'){
dp
[i][j]=0;
}else{
int up = dp
[i-1][j];
int left = dp
[i][j-1];
int ul = dp
[i-1][j-1];
if(up==left && up==ul){
dp
[i][j]=up+1;
}else{
int m = Math.min(up,Math.min(left,ul));
dp
[i][j]=m+1;
}
}
}
}
for(int i=0;i<dp.length;i++){
for(int j=0;j<dp
[0].length;j++){
bc = Math.max(bc,dp
[i][j]);
}
}
int area = bc*bc;
return area;
}
} import java.util.*;
public class Solution {
public int solve (char[][] grap) {
int n = grap.length;
if(n == 0)return 0;
int m = grap[0].length;
int f[][] = new int[n + 3][m + 3];
int len = 0;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
if(grap[i - 1][j - 1] == '1'){
f[i][j] = Math.min(f[i - 1][j - 1],Math.min(f[i - 1][j],f[i][j - 1])) + 1;
len = Math.max(len,f[i][j]);
}
}
}
return len * len;
}
} class Solution {
public:
/**
dp[i][j]:以第i行j列为最右下角元素 前i行j列的最大边长
当第i行j列元素为1时,dp[i][j]=min(dp[i-1][j],min(dp[i-1][j-1],dp[i][j-1]))+ 1;
当第i行j列元素为0时,dp[i][j]=0;
*/
int solve(vector<vector<char> >& matrix) {
int height = matrix.size();
if(!height) return 0;
int width = matrix[0].size();
vector<vector<int> > dp(height+1,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] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i][j - 1]))+ 1;
maxSide = max(maxSide, dp[i][j]);
}
}
}
//返回正方形的面积
return maxSide * maxSide;
}
}; public int solve (char[][] matrix) {
if(matrix == null || matrix.length == 0) return 0;
Stack<Integer> stack = new Stack<>();
int maxRes = 0;
int m = matrix.length, n = matrix[0].length;
int[] arr = new int[n+2];
for(int i = 0; i < m; i++){
stack.push(0);
for(int j = 1; j < n+2; j++){
if(j < n+1){
if(matrix[i][j-1] == '1'){
arr[j]++;
}else{
arr[j] = 0;
}
}
while(!stack.isEmpty() && arr[stack.peek()] > arr[j]){
int length = Math.min(arr[stack.pop()], j-stack.peek()-1);
maxRes = Math.max(maxRes, length);
}
stack.push(j);
}
while(!stack.isEmpty()) stack.pop();
}
return maxRes*maxRes;
} public int solve (char[][] matrix) {
if(matrix == null || matrix.length == 0) return 0;
int m = matrix.length, n = matrix[0].length;
int[][] dp = new int[m+1][n+1];
int max = 0;
for(int i = 1; i < m+1; i++){
for(int j = 1; j < n+1; j++){
if(matrix[i-1][j-1] == '1'){
dp[i][j] = Math.min(dp[i-1][j-1], Math.min(dp[i-1][j], dp[i][j-1])) + 1;
max = Math.max(max, dp[i][j]);
}
}
}
return max*max;
} class Solution {
public:
int solve(vector<vector<char> >& matrix) {
// write code here
int maxSide=0;
int m=matrix.size(),n=matrix[0].size();
vector<vector<int>> dp(m,vector<int>(n));
//动态规划
//数组含义:dp[i][j]表示当前最大边长
//递推公式:正方形,当遍历到一个1时,需要判断左上,上,左是否都为1.都为1则加1,不为1则不变由于是01矩阵,只需要利用min函数即可
//初始化:dp数组边长应该都为0,不需要特别初始化
//遍历顺序,根据递推公式,从上到下,从左到右即可
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(matrix[i][j]=='1'){
if(i==0||j==0) dp[i][j]=1;//特殊情况,没有左上,上,左.默认边长为1的正方形
else dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1;
}
maxSide=max(maxSide,dp[i][j]);//每次计算完需要比较存储
}
}
return maxSide*maxSide;
}
};
用dp[i][j]表示以matrix[i][j]为右下角的全为1组成的最大正方形的边长,则:
1. 若matrix[i][j] == 0, 则dp[i][j] = 0
2. 若matrix[i][j] == 1, 则dp[i][j] = min{dp[i-1][j], dp[i][j-1], dp[i-1][j-1]} + 1
原因可以看下面这张图:
class Solution { public: /** * 最大正方形 * @param matrix char字符型vector<vector<>> * @return int整型 */ int solve(vector<vector<char> >& matrix) { if(matrix.size()==0 || matrix[0].size()==0) { return 0; } int Rows = matrix.size(), Cols = matrix[0].size(); vector<vector<int>> dp(Rows, vector<int>(Cols, 0)); int maxSide = 0; for(int i = 0; i < Rows; i++) { for(int j = 0; j < Cols; j++) { if(matrix[i][j] == '1') { if(i==0 || j==0) { dp[i][j] = 1; } else { dp[i][j] = std::min(std::min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1; } } maxSide = std::max(maxSide, dp[i][j]); } } return (long long)maxSide * maxSide; } };