📌  相关文章
📜  最大子矩阵区域的计数比1的计数大1,比0的计数大1

📅  最后修改于: 2021-05-07 01:43:46             🧑  作者: Mango

给定一个N x N的二进制矩阵。问题在于找到最大面积的子矩阵,其计数的1大于1的计数比0的计数大。
例子:

Input : mat[][] = { {1, 0, 0, 1},
                    {0, 1, 1, 1},
                    {1, 0, 0, 0},
                    {0, 1, 0, 1} }
Output : 9
The sub-matrix defined by the boundary values (1, 1) and (3, 3).
{ {1, 0, 0, 1},
  {0, 1, 1, 1},
  {1, 0, 0, 0},
  {0, 1, 0, 1} }

天真的方法:检查给定2D矩阵中的每个可能的矩形。该解决方案需要4个嵌套循环,并且该解决方案的时间复杂度为O(n ^ 4)。

高效的方法:一种有效的方法将是使用最长的子数组,其计数为1s的计数比计数为0的计数多一个,这将时间复杂度降低到O(n ^ 3)。想法是一一固定左和右列,并找到最大长度的连续行,其每个左和右列对的计数为1的数字比0的计数大。查找每个固定的左右列对的顶部和底部行号(具有最大长度)。要找到顶部和底部的行号,请计算从左到右每一行中元素的总和,并将这些总和存储在一个名为temp []的数组中(在添加0时将其视为-1)。因此,temp [i]指示第i行中从左到右的元素总和。使用最长计数为1s的子数组多于0s的方法,temp []数组用于通过获取开始和结束来获得temp []的最大长度的子数组,该数组的temp []的计数比1的计数多于0的计数行号,然后这些值可用于查找最大可能的区域,并以左和右为边界列。要获得总的最大面积,请将此面积与到目前为止的最大面积进行比较。

下面是上述方法的实现:

C++
// C++ implementation to find
// the maximum area sub-matrix
// having count of 1's
// one more than count of 0's
#include 
 
using namespace std;
 
#define SIZE 10
 
// function to find the length of longest
// subarray having count of 1's one more
// than count of 0's
int lenOfLongSubarr(int arr[], int n,
                    int& start, int& finish)
{
    // unordered_map 'um' implemented as
    // hash table
    unordered_map um;
    int sum = 0, maxLen = 0;
 
    // traverse the given array
    for (int i = 0; i < n; i++) {
 
        // accumulating sum
        sum += arr[i];
 
        // when subarray starts form index '0'
        if (sum == 1) {
            start = 0;
            finish = i;
            maxLen = i + 1;
        }
 
        // make an entry for 'sum' if it is
        // not present in 'um'
        else if (um.find(sum) == um.end())
            um[sum] = i;
 
        // check if 'sum-1' is present in 'um'
        // or not
        if (um.find(sum - 1) != um.end()) {
 
            // update 'start', 'finish'
            // and maxLength
            if (maxLen < (i - um[sum - 1]))
                start = um[sum - 1] + 1;
            finish = i;
            maxLen = i - um[sum - 1];
        }
    }
 
    // required maximum length
    return maxLen;
}
 
// function to find the maximum
// area sub-matrix having
// count of 1's one more than count of 0's
void largestSubmatrix(int mat[SIZE][SIZE], int n)
{
    // variables to store final
    // and intermediate results
    int finalLeft, finalRight, finalTop, finalBottom;
    int temp[n], maxArea = 0, len, start, finish;
 
    // set the left column
    for (int left = 0; left < n; left++) {
 
        // Initialize all elements of temp as 0
        memset(temp, 0, sizeof(temp));
 
        // Set the right column for the
        // left column set by outer loop
        for (int right = left; right < n; right++) {
 
            // Calculate sum between current left and right
            // for every row 'i', consider '0' as '-1'
            for (int i = 0; i < n; ++i)
                temp[i] += mat[i][right] == 0 ? -1 : 1;
 
            // function to set the 'start' and 'finish'
            // variables having index values of
            // temp[] which contains the longest
            // subarray of temp[] having count of 1's
            // one more than count of 0's
            len = lenOfLongSubarr(temp, n, start, finish);
 
            // Compare with maximum area
            // so far and accordingly update the
            // final variables
            if ((len != 0) && (maxArea < (finish - start + 1)
                                             * (right - left + 1))) {
                finalLeft = left;
                finalRight = right;
                finalTop = start;
                finalBottom = finish;
                maxArea = (finish - start + 1) * (right - left + 1);
            }
        }
    }
 
    // Print final values
    cout << "(Top, Left): (" << finalTop << ", "
         << finalLeft << ")\n";
 
    cout << "(Bottom, Right): (" << finalBottom << ", "
         << finalRight << ")\n";
 
    cout << "Maximum area: " << maxArea;
}
 
// Driver Code
int main()
{
    int mat[SIZE][SIZE] = { { 1, 0, 0, 1 },
                            { 0, 1, 1, 1 },
                            { 1, 0, 0, 0 },
                            { 0, 1, 0, 1 } };
    int n = 4;
    largestSubmatrix(mat, n);
    return 0;
}


Java
// Java implementation to find
// the maximum area sub-matrix
// having count of 1's
// one more than count of 0's
import java.util.*;
 
class GFG
{
 
static int start, finish;
 
// Function to find the length of longest
// subarray having count of 1's one more
// than count of 0's
static int lenOfLongSubarr(int []arr, int n)
{
     
    // unordered_map 'um' implemented as
    // hash table
    HashMap um = new HashMap();
     
    int sum = 0, maxLen = 0;
 
    // Traverse the given array
    for(int i = 0; i < n; i++)
    {
         
        // Accumulating sum
        sum += arr[i];
 
        // When subarray starts form index '0'
        if (sum == 1)
        {
            start = 0;
            finish = i;
            maxLen = i + 1;
        }
 
        // Make an entry for 'sum' if it is
        // not present in 'um'
        else if (!um.containsKey(sum))
            um.put(sum,i);
 
        // Check if 'sum-1' is present in 'um'
        // or not
        if (um.containsKey(sum - 1))
        {
             
            // Update 'start', 'finish'
            // and maxLength
            if (maxLen < (i - um.get(sum - 1)))
                start = um.get(sum - 1) + 1;
                 
            finish = i;
            maxLen = i - um.get(sum - 1);
        }
    }
     
    // Required maximum length
    return maxLen;
}
 
// Function to find the maximum
// area sub-matrix having
// count of 1's one more than count of 0's
static void largestSubmatrix(int [][]mat, int n)
{
     
    // Variables to store final
    // and intermediate results
    int finalLeft = 0, finalRight = 0,
        finalTop = 0, finalBottom = 0;
    int maxArea = 0, len;
    finish = 0;
    start=0;
     
    int []temp = new int[n];
     
    // Set the left column
    for(int left = 0; left < n; left++)
    {
         
        // Initialize all elements of temp as 0
        Arrays.fill(temp, 0);
 
        // Set the right column for the
        // left column set by outer loop
        for(int right = left; right < n; right++)
        {
             
            // Calculate sum between current left
            // and right for every row 'i',
            // consider '0' as '-1'
            for(int i = 0; i < n; ++i)
                temp[i] += mat[i][right] == 0 ? -1 : 1;
 
            // Function to set the 'start' and 'finish'
            // variables having index values of
            // temp[] which contains the longest
            // subarray of temp[] having count of 1's
            // one more than count of 0's
            len = lenOfLongSubarr(temp, n);
 
            // Compare with maximum area
            // so far and accordingly update the
            // final variables
            if ((len != 0) &&
                (maxArea < (finish - start + 1) *
                            (right - left + 1)))
            {
                finalLeft = left;
                finalRight = right;
                finalTop = start;
                finalBottom = finish;
                maxArea = (finish - start + 1) *
                            (right - left + 1);
            }
        }
    }
 
    // Print final values
    System.out.print("(Top, Left): (" + finalTop +
                ", " + finalLeft + ")\n");
     
    System.out.print("(Bottom, Right): (" + finalBottom +
                    ", " + finalRight + ")\n");
     
    System.out.print("Maximum area: " + maxArea);
 
}
 
// Driver code
public static void main(String[] args)
{
    int [][]mat = new int[][]{ { 1, 0, 0, 1 },
                            { 0, 1, 1, 1 },
                            { 1, 0, 0, 0 },
                            { 0, 1, 0, 1 } };
    int n = 4;
     
    largestSubmatrix(mat, n);
}
}
 
// This code is contributed by pratham76


Python3
# Python implementation to find
# the maximum area sub-matrix
# having count of 1's
# one more than count of 0's
 
# function to find the length of longest
# subarray having count of 1's one more
# than count of 0's
def lenOfLongSubarr(arr, n, start, finish):
   
  # unordered_map 'um' implemented as
  # hash table
  um = {}
  sum = 0
  maxLen = 0
   
  # traverse the given array
  for i in range(n):
     
    # accumulating sum
    sum += arr[i]
     
    # when subarray starts form index '0'
    if (sum == 1):
      start = 0
      finish = i
      maxLen = i + 1
       
    # make an entry for 'sum' if it is
    # not present in 'um'
    elif (sum not in um):
      um[sum] = i
       
    # check if 'sum-1' is present in 'um'
    # or not
    if (sum - 1 in um):
       
      # update 'start', 'finish'
      # and maxLength
      if (maxLen < (i - um[sum - 1])):
        start = um[sum - 1] + 1
        finish = i
        maxLen = i - um[sum - 1]
 
  # required maximum length
  return [maxLen,start,finish]
 
# function to find the maximum
# area sub-matrix having
# count of 1's one more than count of 0's
def largestSubmatrix(mat, n):
   
  # variables to store final
  # and intermediate results
  temp = []
  maxArea = 0
   
  # set the left column
  for left in range(n):
     
    # Initialize all elements of temp as 0
    temp = [0 for i in range(n)]
     
    # Set the right column for the
    # left column set by outer loop
    for right in range(left, n):
       
      # Calculate sum between current left and right
      # for every row 'i', consider '0' as '-1'
      for i in range(n):
        if mat[i][right] == 0:
          temp[i] -= 1
        else:
          temp[i] += 1
 
      # function to set the 'start' and 'finish'
      # variables having index values of
      # temp[] which contains the longest
      # subarray of temp[] having count of 1's
      # one more than count of 0's
      start = 0
      finish = 0
      fc = lenOfLongSubarr(temp, n, start, finish)
      len = fc[0]
      start = fc[1]
      finish = fc[2]
       
      # Compare with maximum area
      # so far and accordingly update the
      # final variables
      if ((len != 0) and (maxArea < (finish - start + 1) * (right - left + 1))):
        finalLeft = left
        finalRight = right
        finalTop = start
        finalBottom = finish
        maxArea = (finish - start + 1) * (right - left + 1)
 
  # Print final values
  print("(Top, Left): (",finalTop,", ",finalLeft,")")
  print("(Bottom, Right): (",finalBottom, ", ",finalRight,")")
  print("Maximum area: ", maxArea)
 
# Driver Code
mat = [[1, 0, 0, 1 ], [ 0, 1, 1, 1 ], [ 1, 0, 0, 0 ], [ 0, 1, 0, 1 ]]
n = 4
largestSubmatrix(mat, n)
 
# This code is contributed by rohitsingh07052


C#
// C# implementation to find
// the maximum area sub-matrix
// having count of 1's
// one more than count of 0's
using System;
using System.Collections.Generic;
using System.Collections;
 
class GFG{
 
// Function to find the length of longest
// subarray having count of 1's one more
// than count of 0's
static int lenOfLongSubarr(int []arr, int n,
                       ref int start, ref int finish)
{
     
    // unordered_map 'um' implemented as
    // hash table
    Dictionary um = new Dictionary();
     
    int sum = 0, maxLen = 0;
  
    // Traverse the given array
    for(int i = 0; i < n; i++)
    {
         
        // Accumulating sum
        sum += arr[i];
  
        // When subarray starts form index '0'
        if (sum == 1)
        {
            start = 0;
            finish = i;
            maxLen = i + 1;
        }
  
        // Make an entry for 'sum' if it is
        // not present in 'um'
        else if (!um.ContainsKey(sum))
            um[sum] = i;
  
        // Check if 'sum-1' is present in 'um'
        // or not
        if (um.ContainsKey(sum - 1))
        {
             
            // Update 'start', 'finish'
            // and maxLength
            if (maxLen < (i - um[sum - 1]))
                start = um[sum - 1] + 1;
                 
            finish = i;
            maxLen = i - um[sum - 1];
        }
    }
     
    // Required maximum length
    return maxLen;
}
  
// Function to find the maximum
// area sub-matrix having
// count of 1's one more than count of 0's
static void largestSubmatrix(int [,]mat, int n)
{
     
    // Variables to store final
    // and intermediate results
    int finalLeft = 0, finalRight = 0,
         finalTop = 0, finalBottom = 0;
    int maxArea = 0, len, start = 0, finish = 0;
     
    int []temp = new int[n];
     
    // Set the left column
    for(int left = 0; left < n; left++)
    {
         
        // Initialize all elements of temp as 0
        Array.Fill(temp, 0);
  
        // Set the right column for the
        // left column set by outer loop
        for(int right = left; right < n; right++)
        {
             
            // Calculate sum between current left
            // and right for every row 'i',
            // consider '0' as '-1'
            for(int i = 0; i < n; ++i)
                temp[i] += mat[i, right] == 0 ? -1 : 1;
  
            // Function to set the 'start' and 'finish'
            // variables having index values of
            // temp[] which contains the longest
            // subarray of temp[] having count of 1's
            // one more than count of 0's
            len = lenOfLongSubarr(temp, n, ref start,
                                           ref finish);
  
            // Compare with maximum area
            // so far and accordingly update the
            // final variables
            if ((len != 0) &&
                (maxArea < (finish - start + 1) *
                             (right - left + 1)))
            {
                finalLeft = left;
                finalRight = right;
                finalTop = start;
                finalBottom = finish;
                maxArea = (finish - start + 1) *
                            (right - left + 1);
            }
        }
    }
  
    // Print final values
    Console.Write("(Top, Left): (" + finalTop +
                  ", " + finalLeft + ")\n");
     
    Console.Write("(Bottom, Right): (" + finalBottom +
                     ", " + finalRight + ")\n");
     
    Console.Write("Maximum area: " + maxArea);
  
}
 
// Driver code
public static void Main(string[] args)
{
    int [,]mat = new int[,]{ { 1, 0, 0, 1 },
                             { 0, 1, 1, 1 },
                             { 1, 0, 0, 0 },
                             { 0, 1, 0, 1 } };
    int n = 4;
     
    largestSubmatrix(mat, n);
}
}
 
// This code is contributed by rutvik_56


输出:
(Top, Left): (1, 1)
(Bottom, Right): (3, 3)
Maximum area: 9

时间复杂度: O(N 3 )。
辅助空间: O(N)。