📜  检查矩阵是否包含以0为边界元素的正方形子矩阵

📅  最后修改于: 2021-05-04 12:24:19             🧑  作者: Mango

给定一个N * N二进制矩阵arr [] [] ,任务是检查矩阵是否包含至少大小为2 x 2的正方形,其边界仅由0 s组成。

例子:

方法:

  1. 正方形由其最上面和最下面的行以及最左边和最右边的列定义。
  2. 给定形成有效正方形的一对行和一对列,您可以轻松确定相关的正方形是否是带有两个for循环的零的正方形。
  3. 需要迭代输入矩阵arr [] []中的每个有效正方形。
  4. 我们可以从最外面的正方形开始迭代,然后递归地进入矩阵。
  5. 从(r1,c1)和(r2,c2)向内移动时,我们有5个选项,它们将生成方矩阵:
    a)(r1 + 1,c1 +1),(r2 – 1,c2 – 1)
    b)(r1,c1 +1),(r2 – 1,c2)
    c)(r1 + 1,c1),(r2,c2 – 1)
    d)(r1 + 1,c1 +1),(r2,c2)
    e)(r1,c1),(r2 – 1,c2 – 1)
  6. 由于该问题有许多重叠的子问题,因此我们需要使用高速缓存/内存化来避免重复计算。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
 
#include 
using namespace std;
 
bool hasSquareOfZeroes(
    vector >& matrix,
    int r1, int c1, int r2, int c2,
    unordered_map& cache);
 
bool isSquareOfZeroes(
    vector >& matrix,
    int r1, int c1,
    int r2, int c2);
 
// Function checks if square
// with all 0's in boundary
// exists in the matrix
bool squareOfZeroes(
    vector > matrix)
{
    int lastIdx = matrix.size() - 1;
    unordered_map cache;
    return hasSquareOfZeroes(
        matrix,
        0, 0,
        lastIdx,
        lastIdx,
        cache);
}
 
// Function iterate inward in
// the matrix and checks the
// square obtained and memoize/cache
// the result to avoid duplicate computation
 
// r1 is the top row,
// c1 is the left col
// r2 is the bottom row,
// c2 is the right
bool hasSquareOfZeroes(
    vector >& matrix,
    int r1, int c1, int r2, int c2,
    unordered_map& cache)
{
    if (r1 >= r2 || c1 >= c2)
        return false;
    string key = to_string(r1) + '-'
                 + to_string(c1) + '-'
                 + to_string(r2) + '-'
                 + to_string(c2);
 
    if (cache.find(key) != cache.end())
        return cache[key];
 
    cache[key]
        = isSquareOfZeroes(
              matrix, r1, c1, r2, c2)
          || hasSquareOfZeroes(
                 matrix, r1 + 1, c1 + 1,
                 r2 - 1, c2 - 1, cache)
          || hasSquareOfZeroes(
                 matrix, r1, c1 + 1,
                 r2 - 1, c2, cache)
          || hasSquareOfZeroes(
                 matrix, r1 + 1, c1,
                 r2, c2 - 1, cache)
          || hasSquareOfZeroes(
                 matrix, r1 + 1, c1 + 1,
                 r2, c2, cache)
          || hasSquareOfZeroes(
                 matrix, r1, c1,
                 r2 - 1, c2 - 1, cache);
 
    return cache[key];
}
 
// Function checks if the
// boundary of the square
// consists of 0's
bool isSquareOfZeroes(
    vector >& matrix,
    int r1, int c1,
    int r2, int c2)
{
    for (int row = r1; row < r2 + 1; row++) {
        if (matrix[row][c1] != 0
            || matrix[row][c2] != 0)
            return false;
    }
    for (int col = c1; col < c2 + 1; col++) {
        if (matrix[r1][col] != 0
            || matrix[r2][col] != 0)
            return false;
    }
    return true;
}
 
// Driver Code
int main()
{
    vector > matrix{
        { 1, 1, 1, 0, 1, 0 },
        { 0, 0, 0, 0, 0, 1 },
        { 0, 1, 1, 1, 0, 1 },
        { 0, 0, 0, 1, 0, 1 },
        { 0, 1, 1, 1, 0, 1 },
        { 0, 0, 0, 0, 0, 1 }
    };
    int ans;
    ans = squareOfZeroes(matrix);
 
    if (ans == 1) {
        cout << "True" << endl;
    }
    else {
        cout << "False" << endl;
    }
}


Java
// Java implementation of the above approach
import java.io.*;
import java.util.*;
 
class GFG
{
 
    // Function checks if square
    // with all 0's in boundary
    // exists in the matrix
    static int squareOfZeroes(int[][] matrix)
    {
        int lastIdx = matrix.length - 1;
        Map cache
            = new HashMap();
        return (hasSquareOfZeroes(matrix, 0, 0, lastIdx,
                                 lastIdx, cache)) ? 1 : 0;
    }
 
    // Function iterate inward in
    // the matrix and checks the
    // square obtained and memoize/cache
    // the result to avoid duplicate computation
 
    // r1 is the top row,
    // c1 is the left col
    // r2 is the bottom row,
    // c2 is the right
    static boolean hasSquareOfZeroes(int[][] matrix, int r1, int c1,
                                     int r2, int c2,
                                     Map cache)
    {
        if (r1 >= r2 || c1 >= c2)
            return false;
        String key = r1 + "-" + c1 +
          "-" + r2 + "-" + c2;
 
        if (cache.containsKey(key))
            return cache.get(key);
 
        cache.put(
            key,
            isSquareOfZeroes(matrix, r1, c1, r2, c2)
                || hasSquareOfZeroes(matrix, r1 + 1, c1 + 1,
                                     r2 - 1, c2 - 1, cache)
                || hasSquareOfZeroes(matrix, r1, c1 + 1,
                                     r2 - 1, c2, cache)
                || hasSquareOfZeroes(matrix, r1 + 1, c1, r2,
                                     c2 - 1, cache)
                || hasSquareOfZeroes(matrix, r1 + 1, c1 + 1,
                                     r2, c2, cache)
                || hasSquareOfZeroes(matrix, r1, c1, r2 - 1,
                                     c2 - 1, cache));
 
        return cache.get(key);
    }
 
    // Function checks if the
    // boundary of the square
    // consists of 0's
    static boolean isSquareOfZeroes(int[][] matrix,
                                    int r1, int c1,
                                    int r2, int c2)
    {
        for (int row = r1; row < r2 + 1; row++)
        {
            if (matrix[row][c1] != 0
                || matrix[row][c2] != 0)
                return false;
        }
        for (int col = c1; col < c2 + 1; col++)
        {
            if (matrix[r1][col] != 0
                || matrix[r2][col] != 0)
                return false;
        }
        return true;
    }
   
    // Driver Code
    public static void main(String[] args)
    {
        int[][] matrix = {
            { 1, 1, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 1 },
            { 0, 1, 1, 1, 0, 1 }, { 0, 0, 0, 1, 0, 1 },
            { 0, 1, 1, 1, 0, 1 }, { 0, 0, 0, 0, 0, 1 }
        };
        int ans;
        ans = squareOfZeroes(matrix);
 
        if (ans == 1)
        {
            System.out.println("True");
        }
        else
        {
            System.out.println("False");
        }
    }
}
 
// This code is contributed by jitin


Python3
# Python3 implementation of the above approach
 
# Function checks if square
# with all 0's in boundary
# exists in the matrix
def squareOfZeroes():
     
    global matrix, cache
    lastIdx = len(matrix) - 1
     
    return hasSquareOfZeroes(0, 0, lastIdx,
                                   lastIdx)
 
# Function iterate inward in
# the matrix and checks the
# square obtained and memoize/cache
# the result to avoid duplicate computation
 
# r1 is the top row,
# c1 is the left col
# r2 is the bottom row,
# c2 is the right
def hasSquareOfZeroes(r1, c1, r2, c2):
     
    global matrix, cache
 
    if (r1 >= r2 or c1 >= c2):
        return False
         
    key = (str(r1) + '-' + str(c1) + '-' +
           str(r2) + '-' + str(c2))
 
    if (key in cache):
        return cache[key]
 
    cache[key] = (isSquareOfZeroes(r1, c1, r2, c2) or
                 hasSquareOfZeroes(r1 + 1, c1 + 1,
                                   r2 - 1, c2 - 1))
    cache[key] = (cache[key] or
                  hasSquareOfZeroes(r1, c1 + 1,
                                        r2 - 1, c2) or
                  hasSquareOfZeroes(r1 + 1, c1,
                                r2, c2 - 1))
    cache[key] = (cache[key] or
                  hasSquareOfZeroes(r1 + 1, c1 + 1,
                                    r2, c2) or
                  hasSquareOfZeroes(r1, c1, r2 - 1,
                                            c2 - 1))
 
    return cache[key]
 
# Function checks if the
# boundary of the square
# consists of 0's
def isSquareOfZeroes(r1, c1, r2, c2):
     
    global matrix
 
    for row in range(r1, r2 + 1):
        if (matrix[row][c1] != 0 or
            matrix[row][c2] != 0):
            return False
             
    for col in range(c1, c2 + 1):
        if (matrix[r1][col] != 0 or
            matrix[r2][col] != 0):
            return False
 
    return True
 
# Driver Code
if __name__ == '__main__':
     
    cache = {}
    matrix = [ [ 1, 1, 1, 0, 1, 0 ],
               [ 0, 0, 0, 0, 0, 1 ],
               [ 0, 1, 1, 1, 0, 1 ],
               [ 0, 0, 0, 1, 0, 1 ],
               [ 0, 1, 1, 1, 0, 1 ],
               [ 0, 0, 0, 0, 0, 1 ] ]
 
    ans = squareOfZeroes()
 
    if (ans == 1):
        print("True")
    else:
        print("False")
 
# This code is contributed by mohit kumar 29


C#
// C# implementation of the above approach
using System;
using System.Collections.Generic;
class GFG
{
 
  // Function checks if square
  // with all 0's in boundary
  // exists in the matrix
  static int squareOfZeroes(int[,] matrix)
  {
    int lastIdx = matrix.GetLength(0) - 1;
    Dictionary cache = new Dictionary();
    if(hasSquareOfZeroes(matrix, 0, 0, lastIdx,lastIdx, cache))
    {
      return 1;
    }
    else
    {
      return 0;
    }
  }
 
  // Function iterate inward in
  // the matrix and checks the
  // square obtained and memoize/cache
  // the result to avoid duplicate computation
 
  // r1 is the top row,
  // c1 is the left col
  // r2 is the bottom row,
  // c2 is the right
  static bool hasSquareOfZeroes(int[,] matrix, int r1,
                                int c1,int r2, int c2,
                                Dictionary cache)
  {
    if (r1 >= r2 || c1 >= c2)
    {
      return false;
    }
    string key = r1 + "-" + c1 + "-" + r2 + "-" + c2;
    if (cache.ContainsKey(key))
    {
      return cache[key];
    }
    cache[key] = (isSquareOfZeroes(matrix, r1, c1, r2, c2) ||
                  hasSquareOfZeroes(matrix, r1 + 1, c1 + 1,
                                    r2 - 1, c2 - 1, cache) ||
                  hasSquareOfZeroes(matrix, r1, c1 + 1,r2 - 1,
                                    c2, cache) ||
                  hasSquareOfZeroes(matrix, r1 + 1, c1, r2,
                                    c2 - 1, cache) ||
                  hasSquareOfZeroes(matrix, r1 + 1, c1 + 1,
                                    r2, c2, cache) ||
                  hasSquareOfZeroes(matrix, r1, c1, r2 - 1,
                                    c2 - 1, cache));
    return cache[key];
  }
 
  // Function checks if the
  // boundary of the square
  // consists of 0's
  static bool isSquareOfZeroes(int[,] matrix, int r1,
                               int c1,int r2, int c2)
  {
    for (int row = r1; row < r2 + 1; row++)
    {
      if (matrix[row,c1] != 0 || matrix[row,c2] != 0)
      {
        return false;
      }
 
    }
    for (int col = c1; col < c2 + 1; col++)
    {
      if (matrix[r1,col] != 0 || matrix[r2,col] != 0)
      {
        return false;
      }
    }
    return true;
  }
 
  // Driver Code
  static public void Main ()
  {
    int[,] matrix = {{ 1, 1, 1, 0, 1, 0 },
                     { 0, 0, 0, 0, 0, 1 },
                     { 0, 1, 1, 1, 0, 1 },
                     { 0, 0, 0, 1, 0, 1 },
                     { 0, 1, 1, 1, 0, 1 },
                     { 0, 0, 0, 0, 0, 1 }};
    int ans;
    ans = squareOfZeroes(matrix);
    if(ans == 1)
    {
      Console.WriteLine("True");
 
    }
    else
    {
      Console.WriteLine("False");
    }
  }
}
 
// This code is contributed by avanitrachhadiya2155


输出:
True

时间复杂度: O(N ^ 4)
空间复杂度: O(N ^ 3)

高效的方法:为了优化上述方法,我们需要遵循以下步骤:

  1. 我们需要为矩阵中的每个元素预先计算两个值:每个元素右边的0(包括元素本身)的数目和每个元素下方(包括元素本身)的0的数目。
  2. 我们可以通过从右下角开始遍历矩阵并通过从右向左遍历每一行向上移动矩阵来计算这些值。
  3. 一次,我们计算了矩阵,然后可以检查正方形的边界,它是否由恒定时间内的全0组成。
  4. 要检查正方形的边界,我们只需要查看任何正方形的两个上角下方的0数量,以及同一正方形的两个左角右侧的0数量。