📌  相关文章
📜  全为 1 的最大大小矩形二进制子矩阵

📅  最后修改于: 2022-05-13 01:57:09.195000             🧑  作者: Mango

全为 1 的最大大小矩形二进制子矩阵

给定一个二进制矩阵,找到最大尺寸的全为 1 的矩形二进制子矩阵。

例子:

Input:
0 1 1 0
1 1 1 1
1 1 1 1
1 1 0 0
Output :
8
Explanation : 
The largest rectangle with only 1's is from 
(1, 0) to (2, 3) which is
1 1 1 1
1 1 1 1 

Input:
0 1 1
1 1 1
0 1 1      
Output:
6
Explanation : 
The largest rectangle with only 1's is from 
(0, 1) to (2, 2) which is
1 1
1 1
1 1

已经有一种算法讨论了一种基于动态规划的解决方案,用于找到1s 的最大正方形

方法:在这篇文章中,讨论了一种有趣的方法,它使用直方图下的最大矩形作为子程序。
如果给定直方图条的高度,则可以找到直方图的最大区域。这样,在每一行中,都可以找到直方图的最大条形区域。要获得全为 1 的最大矩形,用前一行更新下一行并找到直方图下的最大区域,即将每个 1 视为实心方块,将 0 视为空方块并将每一行视为基数。

插图:

Input :
0 1 1 0
1 1 1 1
1 1 1 1
1 1 0 0
Step 1: 
0 1 1 0  maximum area  = 2
Step 2:
row 1  1 2 2 1  area = 4, maximum area becomes 4
row 2  2 3 3 2  area = 8, maximum area becomes 8
row 3  3 4 0 0  area = 6, maximum area remains 8

算法:

  1. 运行循环以遍历行。
  2. 现在如果当前行不是第一行,则按如下方式更新行,如果 matrix[i][j] 不为零,则 matrix[i][j] = matrix[i-1][j] + matrix[i ][j]。
  3. 找到直方图下的最大矩形区域,将第 i 行视为直方图条的高度。这可以按照本文最大矩形区域中的直方图中给出的计算
  4. 对所有行执行前两个步骤并打印所有行的最大面积。

注意:强烈建议先参考这篇文章,因为大部分代码都是从那里获取的。

执行

C++
// C++ program to find largest
// rectangle with all 1s
// in a binary matrix
#include 
using namespace std;
 
// Rows and columns in input matrix
#define R 4
#define C 4
 
// Finds the maximum area under
// the histogram represented
// by histogram.  See below article for details.
 
 
int maxHist(int row[])
{
    // Create an empty stack.
    // The stack holds indexes of
    // hist[] array/ The bars stored
    // in stack are always
    // in increasing order of their heights.
    stack result;
 
    int top_val; // Top of stack
 
    int max_area = 0; // Initialize max area in current
    // row (or histogram)
 
    int area = 0; // Initialize area with current top
 
    // Run through all bars of given histogram (or row)
    int i = 0;
    while (i < C) {
        // If this bar is higher than the bar on top stack,
        // push it to stack
        if (result.empty() || row[result.top()] <= row[i])
            result.push(i++);
 
        else {
            // If this bar is lower than top of stack, then
            // calculate area of rectangle with stack top as
            // the smallest (or minimum height) bar. 'i' is
            // 'right index' for the top and element before
            // top in stack is 'left index'
            top_val = row[result.top()];
            result.pop();
            area = top_val * i;
 
            if (!result.empty())
                area = top_val * (i - result.top() - 1);
            max_area = max(area, max_area);
        }
    }
 
    // Now pop the remaining bars from stack and calculate
    // area with every popped bar as the smallest bar
    while (!result.empty()) {
        top_val = row[result.top()];
        result.pop();
        area = top_val * i;
        if (!result.empty())
            area = top_val * (i - result.top() - 1);
 
        max_area = max(area, max_area);
    }
    return max_area;
}
 
// Returns area of the largest rectangle with all 1s in
// A[][]
int maxRectangle(int A[][C])
{
    // Calculate area for first row and initialize it as
    // result
    int result = maxHist(A[0]);
 
    // iterate over row to find maximum rectangular area
    // considering each row as histogram
    for (int i = 1; i < R; i++) {
 
        for (int j = 0; j < C; j++)
 
            // if A[i][j] is 1 then add A[i -1][j]
            if (A[i][j])
                A[i][j] += A[i - 1][j];
 
        // Update result if area with current row (as last
        // row) of rectangle) is more
        result = max(result, maxHist(A[i]));
    }
 
    return result;
}
 
// Driver code
int main()
{
    int A[][C] = {
        { 0, 1, 1, 0 },
        { 1, 1, 1, 1 },
        { 1, 1, 1, 1 },
        { 1, 1, 0, 0 },
    };
 
    cout << "Area of maximum rectangle is "
         << maxRectangle(A);
 
    return 0;
}


Java
// Java program to find largest rectangle with all 1s
// in a binary matrix
import java.io.*;
import java.util.*;
 
class GFG {
    // Finds the maximum area under the histogram
    // represented by histogram.  See below article for
 
    static int maxHist(int R, int C, int row[])
    {
        // Create an empty stack. The stack holds indexes of
        // hist[] array/ The bars stored in stack are always
        // in increasing order of their heights.
        Stack result = new Stack();
 
        int top_val; // Top of stack
 
        int max_area = 0; // Initialize max area in current
        // row (or histogram)
 
        int area = 0; // Initialize area with current top
 
        // Run through all bars of given histogram (or row)
        int i = 0;
        while (i < C) {
            // If this bar is higher than the bar on top
            // stack, push it to stack
            if (result.empty()
                || row[result.peek()] <= row[i])
                result.push(i++);
 
            else {
                // If this bar is lower than top of stack,
                // then calculate area of rectangle with
                // stack top as the smallest (or minimum
                // height) bar. 'i' is 'right index' for the
                // top and element before top in stack is
                // 'left index'
                top_val = row[result.peek()];
                result.pop();
                area = top_val * i;
 
                if (!result.empty())
                    area
                        = top_val * (i - result.peek() - 1);
                max_area = Math.max(area, max_area);
            }
        }
 
        // Now pop the remaining bars from stack and
        // calculate area with every popped bar as the
        // smallest bar
        while (!result.empty()) {
            top_val = row[result.peek()];
            result.pop();
            area = top_val * i;
            if (!result.empty())
                area = top_val * (i - result.peek() - 1);
 
            max_area = Math.max(area, max_area);
        }
        return max_area;
    }
 
    // Returns area of the largest rectangle with all 1s in
    // A[][]
    static int maxRectangle(int R, int C, int A[][])
    {
        // Calculate area for first row and initialize it as
        // result
        int result = maxHist(R, C, A[0]);
 
        // iterate over row to find maximum rectangular area
        // considering each row as histogram
        for (int i = 1; i < R; i++) {
 
            for (int j = 0; j < C; j++)
 
                // if A[i][j] is 1 then add A[i -1][j]
                if (A[i][j] == 1)
                    A[i][j] += A[i - 1][j];
 
            // Update result if area with current row (as
            // last row of rectangle) is more
            result = Math.max(result, maxHist(R, C, A[i]));
        }
 
        return result;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int R = 4;
        int C = 4;
 
        int A[][] = {
            { 0, 1, 1, 0 },
            { 1, 1, 1, 1 },
            { 1, 1, 1, 1 },
            { 1, 1, 0, 0 },
        };
        System.out.print("Area of maximum rectangle is "
                         + maxRectangle(R, C, A));
    }
}
 
// Contributed by Prakriti Gupta


Python3
# Python3 program to find largest rectangle
# with all 1s in a binary matrix
 
# Finds the maximum area under the
# histogram represented
# by histogram. See below article for details.
 
 
class Solution():
    def maxHist(self, row):
        # Create an empty stack. The stack holds
        # indexes of hist array / The bars stored
        # in stack are always in increasing order
        # of their heights.
        result = []
 
        # Top of stack
        top_val = 0
 
        # Initialize max area in current
        max_area = 0
        # row (or histogram)
 
        area = 0  # Initialize area with current top
 
        # Run through all bars of given
        # histogram (or row)
        i = 0
        while (i < len(row)):
 
            # If this bar is higher than the
            # bar on top stack, push it to stack
            if (len(result) == 0) or (row[result[-1]] <= row[i]):
                result.append(i)
                i += 1
            else:
 
                # If this bar is lower than top of stack,
                # then calculate area of rectangle with
                # stack top as the smallest (or minimum
                # height) bar. 'i' is 'right index' for
                # the top and element before top in stack
                # is 'left index'
                top_val = row[result.pop()]
                area = top_val * i
 
                if (len(result)):
                    area = top_val * (i - result[-1] - 1)
                max_area = max(area, max_area)
 
        # Now pop the remaining bars from stack
        # and calculate area with every popped
        # bar as the smallest bar
        while (len(result)):
            top_val = row[result.pop()]
            area = top_val * i
            if (len(result)):
                area = top_val * (i - result[-1] - 1)
 
            max_area = max(area, max_area)
 
        return max_area
 
    # Returns area of the largest rectangle
    # with all 1s in A
    def maxRectangle(self, A):
 
        # Calculate area for first row and
        # initialize it as result
        result = self.maxHist(A[0])
 
        # iterate over row to find maximum rectangular
        # area considering each row as histogram
        for i in range(1, len(A)):
 
            for j in range(len(A[i])):
 
                # if A[i][j] is 1 then add A[i -1][j]
                if (A[i][j]):
                    A[i][j] += A[i - 1][j]
 
            # Update result if area with current
            # row (as last row) of rectangle) is more
            result = max(result, self.maxHist(A[i]))
 
        return result
 
 
# Driver Code
if __name__ == '__main__':
    A = [[0, 1, 1, 0],
         [1, 1, 1, 1],
         [1, 1, 1, 1],
         [1, 1, 0, 0]]
    ans = Solution()
 
    print("Area of maximum rectangle is",
          ans.maxRectangle(A))
 
# This code is contributed
# by Aaryaman Sharma


C#
// C# program to find largest rectangle
// with all 1s in a binary matrix
using System;
using System.Collections.Generic;
 
class GFG {
    // Finds the maximum area under the
    // histogram represented by histogram.
    // See below article for details.
    // https://
    // www.geeksforgeeks.org/largest-rectangle-under-histogram/
    public static int maxHist(int R, int C, int[] row)
    {
        // Create an empty stack. The stack
        // holds indexes of hist[] array.
        // The bars stored in stack are always
        // in increasing order of their heights.
        Stack result = new Stack();
 
        int top_val; // Top of stack
 
        int max_area = 0; // Initialize max area in
        // current row (or histogram)
 
        int area = 0; // Initialize area with
        // current top
 
        // Run through all bars of
        // given histogram (or row)
        int i = 0;
        while (i < C) {
            // If this bar is higher than the
            // bar on top stack, push it to stack
            if (result.Count == 0
                || row[result.Peek()] <= row[i]) {
                result.Push(i++);
            }
 
            else {
                // If this bar is lower than top
                // of stack, then calculate area of
                // rectangle with stack top as
                // the smallest (or minimum height)
                // bar. 'i' is 'right index' for
                // the top and element before
                // top in stack is 'left index'
                top_val = row[result.Peek()];
                result.Pop();
                area = top_val * i;
 
                if (result.Count > 0) {
                    area
                        = top_val * (i - result.Peek() - 1);
                }
                max_area = Math.Max(area, max_area);
            }
        }
 
        // Now pop the remaining bars from
        // stack and calculate area with
        // every popped bar as the smallest bar
        while (result.Count > 0) {
            top_val = row[result.Peek()];
            result.Pop();
            area = top_val * i;
            if (result.Count > 0) {
                area = top_val * (i - result.Peek() - 1);
            }
 
            max_area = Math.Max(area, max_area);
        }
        return max_area;
    }
 
    // Returns area of the largest
    // rectangle with all 1s in A[][]
    public static int maxRectangle(int R, int C, int[][] A)
    {
        // Calculate area for first row
        // and initialize it as result
        int result = maxHist(R, C, A[0]);
 
        // iterate over row to find
        // maximum rectangular area
        // considering each row as histogram
        for (int i = 1; i < R; i++) {
            for (int j = 0; j < C; j++) {
 
                // if A[i][j] is 1 then
                // add A[i -1][j]
                if (A[i][j] == 1) {
                    A[i][j] += A[i - 1][j];
                }
            }
 
            // Update result if area with current
            // row (as last row of rectangle) is more
            result = Math.Max(result, maxHist(R, C, A[i]));
        }
 
        return result;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int R = 4;
        int C = 4;
 
        int[][] A
            = new int[][] { new int[] { 0, 1, 1, 0 },
                            new int[] { 1, 1, 1, 1 },
                            new int[] { 1, 1, 1, 1 },
                            new int[] { 1, 1, 0, 0 } };
        Console.Write("Area of maximum rectangle is "
                      + maxRectangle(R, C, A));
    }
}
 
// This code is contributed by Shrikant13


Javascript


输出
Area of maximum rectangle is 8

复杂性分析:

  • 时间复杂度: O(R x C)。
    只需要遍历一次矩阵,所以时间复杂度是O(RXC)
  • 空间复杂度: O(C)。
    需要堆栈来存储列,因此空间复杂度为 O(C)