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 }

 

你可能感兴趣的:(max)