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 阅读(295) 评论(0) 编辑 收藏 举报