【问题标题】:How can I find the coordinates of the largest all-true rectangle in a 2d array of booleans in less than O(n^3)?如何在小于 O(n^3) 的二维布尔数组中找到最大的全真矩形的坐标?
【发布时间】:2020-12-03 08:41:35
【问题描述】:

目前,我正在使用这个解决方案:

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

我将 true 转换为 1 并将 false 转换为 -infinity,然后找到最大和矩形。根据文章,这个解决方案是 O(n^3),对于我所需要的,它真的不够快。我尝试使用 Max Histogram 方法 (https://www.youtube.com/watch?v=g8bSdXCG-lA),但是存储矩形大小的方式给我找到最终坐标带来了一些麻烦。

C# 中的代码会很棒,但我很乐意采用伪代码并在需要时自己编写。

【问题讨论】:

  • 如果我没看错,答案似乎是:我不能。谢谢你的链接哈哈。编辑:虽然,我知道在包含 0 和 1 的数组中找到最大的 1 数组的 area 可以在 O(rows*cols) 中完成。按理说,可能有一种方法可以在小于 O(n^3) 的时间内找到所述数组的坐标
  • 如果有更好的算法,WIKI 文章会参考该算法。
  • @RobertKasper 你实现了你提到的最大直方图方法吗?如果是这样,请分享您的代码。绝对可以解决O(rows*cols)中的问题,得到矩形的位置。 wiki 文章是关于一个无法如此有效地解决的更普遍的问题。
  • @ciamej geeksforgeeks.org/maximum-size-rectangle-binary-sub-matrix-1s 我在上面的网站上对代码做了一些小的修改(只是改变了数据类型以满足我的需要)。

标签: c# unity3d multidimensional-array rectangles


【解决方案1】:

基于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 left, 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 left, 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, 1, 0 }, 
            new int[] { 1, 1, 1, 1 }, 
            new int[] { 1, 1, 1, 1 }, 
            new int[] { 1, 1, 0, 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); 
    } 
} 

【讨论】:

  • 这太棒了!谢谢:)
  • @RobertKasper 很高兴它解决了您的问题。您可以接受答案(并投赞成票;)
猜你喜欢
  • 2015-11-16
  • 1970-01-01
  • 2021-06-26
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 2021-05-22
  • 2014-09-26
  • 1970-01-01
相关资源
最近更新 更多