zoukankan      html  css  js  c++  java
  • Leetcode: 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.

    难度:90 这是一道非常综合的题目,要求在0-1矩阵中找出面积最大的全1矩阵。刚看到这道题会比较无从下手,brute force就是对于每个矩阵都看一下,总共有m(m+1)/2*n(n+1)/2个子矩阵(原理跟字符串子串类似,字符串的子串数有n(n+1)/2,只是这里是二维情形,所以是两个相乘),复杂度相当高,肯定不是面试官想要的答案,就不继续想下去了。

    看了一下网上的分析,发现这道题可以在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)。

    编程上一些小细节:如果一行中左右两相邻元素值相等,遍历到右边元素(左边元素正在栈顶),需要pop操作的,而不是push

     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[] height = new int[matrix[0].length];
     5         int maxArea = 0;
     6         
     7         for (int row=0; row<matrix.length; row++) {
     8             LinkedList<Integer> stack = new LinkedList<Integer>();
     9             for (int i=0; i<matrix[0].length; i++) {
    10                 if (matrix[row][i] != '0') height[i] = height[i] + 1;
    11                 else height[i] = 0;
    12             }
    13             for (int col=0; col<matrix[0].length; col++) {
    14                 if (stack.size()==0 || height[col]>height[stack.peek()]) {
    15                     stack.push(col);
    16                 }
    17                 else {
    18                     int temp = stack.pop();
    19                     int width = (stack.size()==0)? col : col-stack.peek()-1;
    20                     maxArea = Math.max(maxArea, width*height[temp]);
    21                     col--;
    22                 }
    23             }
    24             while (stack.size() != 0) {
    25                 int temp = stack.pop();
    26                 int width = (stack.size()==0)? height.length : height.length-stack.peek()-1;
    27                 maxArea = Math.max(maxArea, width*height[temp]);
    28             }
    29         }
    30         
    31         return maxArea;
    32     }
    33 }
  • 相关阅读:
    Go语言并发与并行学习笔记(一)
    Tomcat编码问题
    如何为Kafka集群选择合适的Partitions数量
    go局部变量的存储空间是堆还是栈?
    git的一个merge流程
    GO工程和包
    Go运行环境搭建(MacLinux)
    一些Shell命令
    python_17_数据运算
    python_15_os
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/3985337.html
Copyright © 2011-2022 走看看