Maximal Rectangle

Given a 2D boolean matrix filled with False and True, find the largest rectangle containing all True and return its area.

Example

Given a matrix:

[
  [1, 1, 0, 0, 1],
  [0, 1, 0, 0, 1],
  [0, 0, 1, 1, 1],
  [0, 0, 1, 1, 1],
  [0, 0, 0, 0, 1]
]

return 6.

分析:http://blog.csdn.net/linhuanmars/article/details/24444491

这道题的解法灵感来自于Largest Rectangle in Histogram这道题,假设我们把矩阵沿着某一行切下来,然后把切的行作为底面,将自底面往上的矩阵看成一个直方图(histogram)。直方图的中每个项的高度就是从底面行开始往上1的数量。根据Largest Rectangle in Histogram我们就可以求出当前行作为矩阵下边缘的一个最大矩阵。接下来如果对每一行都做一次Largest Rectangle in Histogram,从其中选出最大的矩阵,那么它就是整个矩阵中面积最大的子矩阵。
算法的基本思路已经出来了,剩下的就是一些节省时间空间的问题了。
我们如何计算某一行为底面时直方图的高度呢? 如果重新计算,那么每次需要的计算数量就是当前行数乘以列数。然而在这里我们会发现一些动态规划的踪迹,如果我们知道上一行直方图的高度,我们只需要看新加进来的行(底面)上对应的列元素是不是0,如果是,则高度是0,否则则是上一行直方图的高度加1。利用历史信息,我们就可以在线行时间内完成对高度的更新。我们知道,Largest Rectangle in Histogram的算法复杂度是O(n)。所以完成对一行为底边的矩阵求解复杂度是O(n+n)=O(n)。接下来对每一行都做一次,那么算法总时间复杂度是O(m*n)。
空间上,我们只需要保存上一行直方图的高度O(n),加上Largest Rectangle in Histogram中所使用的空间O(n),所以总空间复杂度还是O(n)。

 1 class Solution {
 2     public int maximalRectangle(char[][] matrix) {
 3         if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0;
 4         int maxArea = 0;
 5         int[] height = new int[matrix[0].length];
 6         for (int i = 0; i < matrix.length; i++) {
 7             for (int j = 0; j < matrix[0].length; j++) {
 8                 height[j] = matrix[i][j] == '0' ? 0 : height[j] + 1;
 9             }
10             maxArea = Math.max(largestRectangleArea(height), maxArea);
11         }
12         return maxArea;
13     }
14     
15     public int largestRectangleArea(int[] height) {
16       if (height == null || height.length == 0) return 0;
17       Stack<Item> items = new Stack<>();
18       int maxArea = 0;
19       for (int i = 0; i < height.length; i++) {
20           if (items.isEmpty() || height[i] >= items.peek().height) {
21               items.push(new Item(height[i], i));
22           } else {
23               Item item = null;
24               while ((!items.isEmpty()) && height[i] < items.peek().height) {
25                   item = items.pop();
26                   maxArea = Math.max(maxArea, (i - item.index) * item.height);
27               }
28               items.push(new Item(height[i], item.index));
29           }
30       }
31       
32       while (!items.isEmpty()) {
33           Item item = items.pop();
34           maxArea = Math.max(maxArea, (height.length - item.index) * item.height);
35       }
36       return maxArea;
37   }
38 }
39 
40 class Item {
41   int height;
42   int index;
43   public Item(int height, int index) {
44       this.height = height;
45       this.index = index;
46   }
47 }

 

posted @ 2016-07-19 11:20  北叶青藤  阅读(153)  评论(0编辑  收藏  举报