【问题标题】:Maximal Square with 0 inside内为 0 的最大平方
【发布时间】:2019-02-16 14:55:19
【问题描述】:

https://leetcode.com/problems/maximal-square/description/中的Maximal Square问题很容易被DP解决。但是如何解决以下问题:

类似于Maximal Square问题,但允许0在正方形内,“inside”表示正方形的边框必须全为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。

有没有更好的算法?

【问题讨论】:

  • 在您的示例中,您不能采用任何 4x4 正方形吗? IE。一个正好适合的正方形。这给出了答案 16。“允许 0 在正方形内”到底是什么意思?
  • 允许多少个 0?否则,最大的正方形总是答案。
  • @Henry 我已经更新了问题。
  • @PhamTrung 正方形的边必须由 1 组成,0 可以在正方形的内部。我已经更新了问题的描述
  • 一些声称可以在 O(n^2) 或 O(n^2 log n) here 中完成的声明,如果它们正确,则需要对其进行测试。其中之一是将 1 包围的 0 替换为 1,然后运行原始 DP 算法

标签: algorithm matrix dynamic-programming


【解决方案1】:

您的问题可以在 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;
}

【讨论】:

    猜你喜欢
    • 2016-04-20
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    相关资源
    最近更新 更多