zoukankan      html  css  js  c++  java
  • 【To Read】

    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.

    一道超难的题目,思想难,同时实现也难。

    本题是动态规划法的高级应用,还依据题目特征优化,难度相当高。

    经提示,知道是max histogram这个题目的思想的灵活运用,就是每一行运用max histogram算法思想计算。

    原来LeetCode把max histogram放在这一题之前是有原因的。没有max histogram这一题的思想基础垫底,是很难理解的。

    LeetCode论坛上的讨论,其实也是这一思想的变种运用,不过感觉讲得并不清楚,他所谓的拖线法,其实就是histogram的倒置。

    只不过并没有严格按照histogram的算法来进行,而是优化了。

    我按histogram算法写的程序用了大概100ms左右,他的算法程序能在40-50ms左右,很快。

    所以我也不得不研究一下他的算法到底优化了什么。

    他使用了三个表L,R,H表,我也画了三个表,对比看看,填填这个表,就能理解这个算法了:

    下面是标准的histogram题目算法的应用程序:

    1. class Solution {  
    2. public:  
    3.     int maximalRectangle(vector<vector<char> > &matrix)   
    4.     {  
    5.         int row = matrix.size();  
    6.         if (row < 1) return 0;  
    7.         int col = matrix[0].size();  
    8.         vector<int> his(col);  
    9.         int maxArea = 0;  
    10.   
    11.         for (int i = row-1; i >= 0; i--)  
    12.         {  
    13.             formHistogram(matrix, i, his);  
    14.             maxArea = max(maxArea, maxHistogram(his));  
    15.         }  
    16.         return maxArea;  
    17.     }  
    18.   
    19.     void formHistogram(vector<vector<char> > &m, int row, vector<int> &his)  
    20.     {  
    21.         for (size_t j = 0; j < m[0].size(); j++)  
    22.         {  
    23.             if (m[row][j]-'0' == 0) his[j] = 0;  
    24.             else if (row != m.size()-1 && m[row+1][j]-'0' == 1)  
    25.             {  
    26.                 his[j]--;  
    27.             }  
    28.             else  
    29.             {  
    30.                 for (int i = row; i >= 0; i--)  
    31.                 {  
    32.                     if (m[i][j]-'0' == 1) his[j]++;  
    33.                     else break;  
    34.                 }  
    35.             }  
    36.         }  
    37.     }  
    38.     int maxHistogram(vector<int> &h)  
    39.     {  
    40.         h.push_back(0);  
    41.         int n = h.size();  
    42.         int maxArea = 0;  
    43.         stack<int> stk;  
    44.   
    45.         for (int i = 0; i < n; )  
    46.         {  
    47.             if (stk.empty() || h[stk.top()] <= h[i]) stk.push(i++);  
    48.             else  
    49.             {  
    50.                 int t = stk.top();  
    51.                 stk.pop();  
    52.                 maxArea = max(maxArea, h[t]*(stk.empty()? i:i-stk.top()-1));  
    53.             }  
    54.         }  
    55.         return maxArea;  
    56.     }  
    57. };  


    优化一点histogram算法的程序:

    1. int maxHistogram(vector<int> &h)  
    2.     {  
    3.         h.push_back(0);  
    4.         int n = h.size();  
    5.         int maxArea = 0;  
    6.         stack<int> stk;  
    7.   
    8.         for (int i = 0; i < n; )  
    9.         {  
    10.             if (stk.empty() || h[stk.top()] <= h[i]) stk.push(i++);  
    11.             else  
    12.             {  
    13.                 int t = stk.top();  
    14.                 stk.pop();  
    15.                 maxArea = max(maxArea, h[t]*(stk.empty()? i:i-stk.top()-1));  
    16.             }  
    17.         }  
    18.         return maxArea;  
    19.     }  
    20.     //================histogram,拖线法实现  
    21.     int maximalRectangle2(vector<vector<char> > &matrix)   
    22.     {  
    23.         int row = matrix.size();  
    24.         if (row < 1) return 0;  
    25.         int col = matrix[0].size();  
    26.         vector<int> his(col);  
    27.         int maxArea = 0;  
    28.   
    29.         for (int i = row-1; i >= 0; i--)  
    30.         {  
    31.             for (int j = 0; j < col; j++)  
    32.             {  
    33.                 if ( matrix[i][j]-'0' == 1) his[j]++;  
    34.                 else his[j] = 0;  
    35.             }  
    36.   
    37.             maxArea = max(maxArea, maxHistogram(his));  
    38.         }  
    39.         return maxArea;  
    40.     }  


    最后是leetcode上的优化算法,也是上图示意图的算法实现:

    1. int maximalRectangle(vector<vector<char> > &matrix) {  
    2.         if (matrix.empty()) {  
    3.             return 0;  
    4.         }  
    5.   
    6.         int n = matrix[0].size();  
    7.         vector<int> H(n);  
    8.         vector<int> L(n);  
    9.         vector<int> R(n, n);  
    10.   
    11.         int ret = 0;  
    12.         for (int i = 0; i < matrix.size(); ++i) {  
    13.             int left = 0, right = n;  
    14.             // calculate L(i, j) from left to right  
    15.             for (int j = 0; j < n; ++j) {  
    16.                 if (matrix[i][j] == '1') {  
    17.                     ++H[j];  
    18.                     L[j] = max(L[j], left);  
    19.                 }  
    20.                 else {  
    21.                     left = j+1;  
    22.                     H[j] = 0; L[j] = 0; R[j] = n;  
    23.                 }  
    24.             }  
    25.             // calculate R(i, j) from right to right  
    26.             for (int j = n-1; j >= 0; --j) {  
    27.                 if (matrix[i][j] == '1') {  
    28.                     R[j] = min(R[j], right);  
    29.                     ret = max(ret, H[j]*(R[j]-L[j]));  
    30.                 }  
    31.                 else {  
    32.                     right = j;  
    33.                 }  
    34.             }  
    35.         }  
    36.   
    37.         return ret;  
    38.     }  


    2014-2-27 update:

    还是下面这个程序比较保险,虽然leetcode上测试,是上一个程序比较快,但是按照理论上计算,两个算法的时间复杂度都是O(n*n),而空间复杂度也都是O(n),那么其实两个方法的实际运行速度都应该差不多的。

    而且主要是下面这个程序更加模块化,更简易;上一个程序很容易出错,下标处理起来很麻烦的,一不小心结果就会出错。

      1. int maximalRectangle(vector<vector<char> > &matrix)   
      2.     {  
      3.         if (matrix.empty() || matrix[0].empty()) return 0;  
      4.         vector<int> height(matrix[0].size()+1);  
      5.         int max_area = 0;  
      6.         for (int i = 0; i < matrix.size(); i++)  
      7.         {  
      8.             for (int j = 0; j < matrix[0].size(); j++)  
      9.             {  
      10.                 if (matrix[i][j] == '1') height[j]++;  
      11.                 else height[j] = 0;  
      12.             }  
      13.             max_area = max(max_area, maxHistogram(height));  
      14.         }  
      15.         return max_area;  
      16.     }  
      17.     int maxHistogram(vector<int> &height)  
      18.     {  
      19.         int ans = 0;  
      20.         stack<int> stk;  
      21.         for (int i = 0; i < height.size(); )  
      22.         {  
      23.             if (stk.empty() || height[stk.top()] < height[i]) stk.push(i++);  
      24.             else  
      25.             {  
      26.                 int idx = stk.top();  
      27.                 stk.pop();  
      28.                 ans = max(ans, (stk.empty()? i:i-stk.top()-1)*height[idx]);  
      29.             }  
      30.         }  
      31.         return ans;  
      32.     }  
  • 相关阅读:
    GUIX 创建工程注意事项
    VS 中bool和BOOL的区别
    git 在Windows上的应用
    rt-thread 相关网站地址
    tcp client
    VS2015 下载地址
    软件各种协议比较(GPL、AGPL、LGPL、Apache、Zlib/Libpng、BSD、MIT)
    UILabel标签
    UIbutton
    数据互转
  • 原文地址:https://www.cnblogs.com/helloWaston/p/4630006.html
Copyright © 2011-2022 走看看