Maximal Rectangle

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.

看到2D,首先想到的就是那个二维矩阵中找最大子矩阵。同样也是可以降级到一维:

给一个array,里面有1 和 0, 找联续1的最大长度。

这个问题很好解决,即function findMax。然后再递归到二维即可。

方法是先把bot定为最底层,然后把top从bot往上移,如果竖向看全1,则将抽象这个矩形的数组本位设为1,否则为0。然后找最大长度,乘上其放大倍数,级top - bot + 1,即为这一层的max。

然后慢慢往上移bot,知道到最高层,找出这些局部max中最大的那个,即为全局max,返回。

 1 public class Solution {
 2     public int maximalRectangle(char[][] matrix) {
 3         // Start typing your Java solution below
 4         // DO NOT write main() function
 5         if(matrix == null || matrix.length == 0) return 0;
 6         int n = matrix.length;
 7         int m = matrix[0].length;
 8         int[] cur = new int[m];
 9         int max = 0;
10         for(int i = 0; i < n; i ++){
11             for(int j = i; j < n; j ++){
12                 for(int l = 0; l < m; l ++){
13                     boolean sig = true;
14                     for(int g = i; g < j + 1; g ++){
15                         if(matrix[g][l] == '0'){
16                             sig = false;
17                             break;
18                         }
19                     }
20                     cur[l] = ((sig == true) ? 1 : 0);
21                 }
22                 int curmax = findMax(cur) * (j - i + 1);
23                 if(curmax > max) max = curmax;
24             }
25         }
26         return max;
27     }
28     public int findMax(int[] vet){
29         int cur = 0;
30         int max = 0;
31         for(int i = 0; i < vet.length; i ++){
32             if(vet[i] == 1) cur ++;
33             else{
34                 if(cur > max) max = cur;
35                 cur = 0;
36             }
37         }
38         if(cur > max) max = cur;
39         return max;
40     }
41 }

这个可以过小测试,大测试超时。 所以引入一个space来存中间结果。这个中间空间即sp。

注意到,当bot不变的时候,每当top往上移的时候,其实不用全部重新算,而是只用拿当前的top层和原来算出来的结果比较即可:

top   原来  ==》 result

1       1                 1

1       0                 0

0       1                 0

0       0                 0

只有一个会改变原来的结果。然后就可以用这个结果去计算了。 所以顺便把findMax也修改了一下。

 1 public class Solution {
 2     public int maximalRectangle(char[][] matrix) {
 3         // Start typing your Java solution below
 4         // DO NOT write main() function
 5         if(matrix == null || matrix.length == 0) return 0;
 6         int n = matrix.length;
 7         int m = matrix[0].length;
 8         int[] cur = new int[m];
 9         int max = 0;
10         char[][] sp = matrix;
11         for(int i = 0; i < n; i ++){
12             for(int j = i; j < n; j ++){
13                 for(int l = 0; l < m; l ++){
14                     if(sp[i][l] == '1' && matrix[j][l] == '0'){
15                         sp[i][l] = '0';
16                     }
17                 }
18                 int curmax = findMax(sp[i]) * (j - i + 1);
19                 if(curmax > max) max = curmax;
20             }
21         }
22         return max;
23     }
24     public int findMax(char[] vet){
25         int cur = 0;
26         int max = 0;
27         for(int i = 0; i < vet.length; i ++){
28             if(vet[i] == '1') cur ++;
29             else{
30                 if(cur > max) max = cur;
31                 cur = 0;
32             }
33         }
34         if(cur > max) max = cur;
35         return max;
36     }
37 }

 在做到这里之后,发现还可以优化,可以将findMax这层循环与原函数的循环合并。

 1 public class Solution {
 2     public int maximalRectangle(char[][] matrix) {
 3         // Start typing your Java solution below
 4         // DO NOT write main() function
 5         if(matrix == null || matrix.length == 0) return 0;
 6         int n = matrix.length;
 7         int m = matrix[0].length;
 8         int[] cur = new int[m];
 9         int max = 0;
10         char[][] sp = matrix;
11         for(int i = 0; i < n; i ++){
12             for(int j = i; j < n; j ++){
13                 int lcur = 0;
14                 int lmax = 0;
15                 for(int l = 0; l < m; l ++){
16                     if(sp[i][l] == '1' && matrix[j][l] == '0'){
17                         sp[i][l] = '0';
18                     }
19                     if(sp[i][l] == '1') lcur ++;
20                     else{
21                         if(lcur > lmax) lmax = lcur;
22                         lcur = 0;
23                     }
24                 }
25                 if(lcur > lmax) lmax = lcur;
26                 int curmax = lmax * (j - i + 1);
27                 if(curmax > max) max = curmax;
28             }
29         }
30         return max;
31     }
32 }

最终,时间复杂度是O(n2m)。 在最开始的时候我们可以人为的选择小的length 作为n,这样可以进一步降低时间复杂度。

 1 public class Solution {
 2     public int maximalRectangle(char[][] matrix) {
 3         if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0;
 4         int len = matrix[0].length;
 5         int max = Integer.MIN_VALUE;
 6         for(int base = 0; base < matrix.length; base ++){
 7             char[] row = matrix[base];
 8             for(int i = base; i < matrix.length; i ++){
 9                 for(int j = 0; j < len; j ++){
10                     if(row[j] == '1') row[j] = matrix[i][j];
11                 }
12                 int cur = 0;
13                 for(int j = 0; j < len; j ++){
14                     cur = row[j] == '1' ? cur + 1 : 0;
15                     max = Math.max(max, cur * (i - base + 1));
16                 }
17             }
18         }
19         return max;
20     }
21 }

 

posted on 2013-09-26 13:45  Step-BY-Step  阅读(294)  评论(0编辑  收藏  举报

导航