如何在小于On ^ 3的2d布尔数组中找到最大的全真矩形的坐标?

问题描述

当前,我正在使用以下解决方案:

https://www.geeksforgeeks.org/maximum-sum-rectangle-in-a-2d-matrix-dp-27/

我将true转换为1,将false转换为-infinity,然后找到最大的求和矩形。根据本文所述,此解决方案为O(n ^ 3),并且对于我所需的速度而言,它的速度确实不够快。我尝试使用最大直方图方法https://www.youtube.com/watch?v=g8bSdXCG-lA),但是矩形尺寸的存储方式给我寻找最终坐标带来了麻烦。

C#中的代码会很棒,但是我很高兴接受伪代码并在需要时自己编写。

解决方法

基于the link provided by the OP

// 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 area,int left,int right) maxHist(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<int> result = new Stack<int>(); 

        int top_val; // Top of stack 
        int left; 

        int max_area = 0; // Initialize max area in current row (or histogram) 
        int max_left = -1;
        int max_right = -1;
    
        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' 
                left = result.Peek();
                top_val = row[left]; 
                result.Pop(); 
                area = top_val * i; 

                if (result.Count > 0) {
                    left = result.Peek() + 1;
                    area = top_val * (i - left); 
                }

                if (area > max_area) {
                    max_area = area;
                    max_left = left;
                    max_right = i - 1;
                }
            } 
        } 

        // Now pop the remaining bars from 
        // stack and calculate area with 
        // every popped bar as the smallest bar 
        while (result.Count > 0) {
            left = result.Peek();
            top_val = row[left]; 
            result.Pop(); 
            area = top_val * i; 
            if (result.Count > 0) { 
                left = result.Peek() + 1;
                area = top_val * (i - left); 
            } 

            if (area > max_area) {
                max_area = area;
                max_left = left;
                max_right = C - 1;
            }
        } 
        return (max_area,max_left,max_right); 
    } 

    // Returns area of the largest 
    // rectangle with all 1s in A[][] 
    public static (int area,int top,int bottom,int right)
        maxRectangle(int R,int C,int[][] A) 
    { 
        int top = 0;
        int bottom = 0;

        // Calculate area for first row 
        // and initialize it as result 
        (int result,int right) = maxHist(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]; 
                } 
            } 

            (int tmp_result,int tmp_left,int tmp_right) = maxHist(C,A[i]);
            // Update result if area with current 
            // row (as last row of rectangle) is more
            if (tmp_result > result) {
                left = tmp_left;
                right = tmp_right;
                bottom = i;
                result = tmp_result;
                top = bottom - (result / (right - left + 1)) + 1;
            }
        } 

        return (result,top,bottom,left,right); 
    } 

    // Driver code 
    public static void Main(string[] args) 
    { 
        int R = 4; 
        int C = 4; 

        int[][] A = new int[][] { 
            new int[] { 0,1,0 },new int[] { 1,1 },0 } 
        }; 
        var result = maxRectangle(R,C,A);
        Console.Write("Area of maximum rectangle is " + result.area + 
            ",rows " + result.top + "-" + result.bottom + 
            ",columns " + result.left + "-" + result.right); 
    } 
}