zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Xcode 统计代码行数
    AWS 根用户MFA丢失后如何处理
    istio 基础入门
    AWS 如何挑选合适EC2实例类型
    word去除页眉首页横线
    word 题注 图注 表注 交叉引用 自动编号
    (转)Python基础热图-参数超级详解
    VScode 运行代码显示:Code is already running!
    pyside2安装避坑
    vscode import numpy error:DLL load failed: The specific module could not be found
  • 原文地址:https://www.cnblogs.com/reynold-lei/p/3340655.html
Copyright © 2011-2022 走看看