内最大为0的正方形

时间:2018-09-12 03:40:04

标签: algorithm matrix dynamic-programming

通过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。

有没有更好的算法?

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;
}