找到给定布尔数组中最大矩形区域的算法

时间:2013-01-25 14:48:51

标签: algorithm geometry

所以问题本身很简单,每个输入,我都给出宽度和高度,两者都不会超过200,然后是一系列0和1来表示2D平面。

喜欢这个。

4 5
0 0 1 1 1
0 1 1 1 1
1 1 1 1 1
1 1 1 1 1

目标是找到右边的区域,面积为12.不用说,矩形只能由1组成。

在写这篇文章的过程中我正在考虑洪水填充,但它必须重新评估阵列中的每个1。什么是最佳算法?

4 个答案:

答案 0 :(得分:2)

类似于以下问题:找到具有最大总和的子矩阵。这可以通过O(n ^ 3)算法来完成。我相信你可以在stackoverflow上找到它或在互联网上搜索。

对于这个问题,你可以用-INF替换0,然后应用上面的算法找到最大的矩形区域。

答案 1 :(得分:1)

我能想到的最好的算法是遍历2D矩阵,从左上角的一个角开始到这个情况下面向右边的一个角,执行以下操作:

对于您找到的每1个,找到最长的1s水平字符串以及垂直字符串。为了提高效率,右边的位置比左边的位置少一个(你仍需要得到它的垂直最大值);你只需在每次达到0时重新开始计数。当你到达下一行时,同样适用。

两个数字的乘积是从该位置开始的矩形的最大可能区域。在另一个数据结构中,存储position,maxWidth和maxHeight,并根据顶部区域最大的区域进行排序。避免放置子矩形以提高效率;你可以通过忽略maxHeight小于或等于其自身值的右邻1来做到这一点。我将数据结构的选择留给您。

现在,您将浏览自己创建的数据结构并从最大矩形开始。找到最接近的0.您将矩形拆分为2个子矩形,排除0所在的水平线和2个子矩形,排除0所在的垂直线。如果0位于边缘,则只能获得3个子矩形如果它在一个角落,只有2.删除矩形,插入新创建的子矩形并保持最大的区域顺序。现在使用数据结构中的下一个矩形重复此过程,直到找到没有0的矩形。那是最大的一个。

这比检查每个可能的子矩阵更有效。

答案 2 :(得分:1)

有几条评论指出线性复杂性的答案,但我想我会提到一个简单的O(n ^ 2)算法。

对于每个单元格,计算完全位于其下方并完全位于其左侧的单元格的数量。您可以通过从左下角开始的行处理,查看其下方的单元格以及从左侧单元格到小数的小计,以线性时间执行此操作。

矩形可以通过其左下角的点和右上角的点来定义。当然,它有四个角落。如果您添加先前计算的左下角和右上角的总计,并减去左上角和右下角的总数,您将获得矩形中的单元格数 - 矩形外的单元格根本不会被计算或被取消了。这个矩形究竟在哪里取决于你在角落的情况下做了什么,以及你究竟如何解释“完全在它下面并完全在它的左边”。但是,如果定义一个矩形的两个角,你可以通过检索四个数字并进行加法和减法来计算其中的总和。

对于由两个点定义的矩形,需要考虑O(n ^ 2)个矩形(因为我将n视为数据的大小,这意味着要搜索的区域具有O(n)个点)。由于我可以在恒定时间内计算每个矩形内的总和并丢弃那些没有总和意味着涵盖所有点的总和,因此总成本为O(n ^ 2)。

答案 3 :(得分:0)

 /*

Given a 2D binary array(2D array of 0's and 1's) with m rows and n columns,find area of largest sub-array(rectangle) 
consisting entirely of 1's.
*/

public int findMaxRectangleArea(int[][] A,int m,int n){
        // m=rows & n=cols according to question

        int[] single;
        int largeX = 0,largest = 0; 
        for (int i = 0; i < m; i++) {
              single = new int[n];            //one d array used to check line by line & it's size will be n
              for (int k = i; k < m; k++) {                // this is used for to run until i contains element
                        int a = 0;
                    int y = k - i + 1;  // is used for row and col of the comming array
                    int shrt = 0,ii = 0,small = 0; 
                                    int mix = 0;
                    int findX = 0; 
                   for (int j = 0; j < n; j++) {
                       single[j] = single[j] + A[k][j]; // postions element are added
                      if (single[j] == y) {           //element position equals
                            shrt = (a == 0) ? j : shrt;       //shortcut
                            a=a+1;
                        if (a > findX) {
                            findX = a;
                            mix = shrt;
                        }
                    } else {
                        a = 0;
                    }
                }
                   a = findX;
                   a = (a == y) ? a - 1 : a;
                         if (a * y > largeX * largest) {  // here i am checking the values with xy
                           largeX = a;
                           largest = y;
                           ii = i;
                           small = mix;
                           }
            }
        }// end of  loop

return largeX*largest;
    }       //end of method




/*
     Time complexity = method contains 2 inner loops so m*m & 1 outer loop n

     so the complexity is------------------->  O((m^2)*n)

     Space Complexity is-------it's directly proportional to the size of the array i.e ---------------> (m*m)+n

*/