通过DP可以轻松解决https://leetcode.com/problems/maximal-square/description/中的最大平方问题。但是如何解决以下问题:
与“最大正方形”问题相似,但允许在正方形内包含0,“内部”表示正方形的边界必须全为1 。 例如,给定以下矩阵:
1 0 1 0 0
1 0 1 1 1
1 1 1 0 1
1 0 1 1 1
返回9。
更新:由于右下角的3 * 3矩阵符合要求,边框必须全部为1,并且正方形内部可以为0。
我想出了一种O(n ^ 3)算法:如果maze[i][j]
取maze[i][j] == 1
作为正方形的右下角,则枚举正方形的边长。如果边长为3,请考虑maze[i - 2][j - 2]
,maze[i][j - 2]
,maze[i - 2][j]
,maze[i][j]
是否形成一个正方形,且每个边的数字均为1。
有没有更好的算法?
答案 0 :(得分:0)
您的问题可以用 O(n * m)的时间和空间复杂度来解决,其中 n 是总行数, m 是总行数矩阵中的列。您可以在下面的代码中对其进行注释,以使其易于理解。 请让我知道,如果您有任何疑问。
#include <bits/stdc++.h>
using namespace std;
void precalRowSum(vector< vector<int> >& grid, vector< vector<int> >&rowSum, int n, int m) {
// contiguous sum upto jth position in ith row
for (int i = 0; i < n; ++i) {
int sum = 0;
for (int j = 0; j < m; ++j) {
if (grid[i][j] == 1) {
sum++;
} else {
sum = 0;
}
rowSum[i][j] = sum;
}
}
}
void precalColSum(vector< vector<int> >& grid, vector< vector<int> >&colSum, int n, int m) {
// contiguous sum upto ith position in jth column
for (int j = 0; j < m; ++j) {
int sum = 0;
for (int i = 0; i < n; ++i) {
if (grid[i][j] == 1) {
sum++;
} else {
sum = 0;
}
colSum[i][j] = sum;
}
}
}
int solve(vector< vector<int> >& grid, int n, int m) {
vector< vector<int> >rowSum(n, vector<int>(m, 0));
vector< vector<int> >colSum(n, vector<int>(m, 0));
// calculate rowwise sum for 1
precalRowSum(grid, rowSum, n, m);
// calculate colwise sum for 1
precalColSum(grid, colSum, n, m);
vector< vector<int> >zerosHeight(n, vector<int>(m, 0));
int ans = 0;
for (int i = 0; i < (n - 1); ++i) {
for (int j = 0; j < m; ++j) {
zerosHeight[i][j] = ( grid[i][j] == 0 );
if (grid[i][j] == 0 && i > 0) {
zerosHeight[i][j] += zerosHeight[i - 1][j];
}
}
if (i == 0) continue;
// perform calculation on ith row
for (int j = 1; j < m; ) {
int height = zerosHeight[i][j];
if (!height) {
j++;
continue;
}
int cnt = 0;
while (j < m && height == zerosHeight[i][j]) {
j++;
cnt++;
}
if ( j == m) break;
if (cnt == height && (i - cnt) >= 0 ) {
// zeros are valid, now check validity for boundries
// Check validity of upper boundray, lower boundary, left boundary, right boundary respectively
if (rowSum[i - cnt][j] >= (cnt + 2) && rowSum[i + 1][j] >= (cnt + 2) &&
colSum[i + 1][j - cnt - 1] >= (cnt + 2) && colSum[i + 1][j] >= (cnt + 2) ){
ans = max(ans, (cnt + 2) * (cnt + 2) );
}
}
}
}
return ans;
}
int main() {
int n, m;
cin>>n>>m;
vector< vector<int> >grid;
for (int i = 0; i < n; ++i) {
vector<int>tmp;
for (int j = 0; j < m; ++j) {
int x;
cin>>x;
tmp.push_back(x);
}
grid.push_back(tmp);
}
cout<<endl;
cout<< solve(grid, n, m) <<endl;
return 0;
}