题目:

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.

代码:

  1. class Solution {
  2. public:
  3. int maximalRectangle(vector<vector<char> >& matrix)
  4. {
  5. if (matrix.empty()) return ;
  6. const int ROW = matrix.size();
  7. const int COL = matrix[].size();
  8. vector<int> height(COL,);
  9. vector<int> l_most(COL,);
  10. vector<int> r_most(COL,COL-);
  11. int max_area = ;
  12. for ( int i = ; i < ROW; ++i )
  13. {
  14. int l_curr = ;
  15. int r_curr = COL-;
  16. // calculate current row's height
  17. for ( int j = ; j < COL; ++j )
  18. {
  19. height[j] = matrix[i][j]=='' ? height[j]+ : ;
  20. }
  21. // from left to right
  22. for ( int j = ; j < COL; ++j )
  23. {
  24. if ( matrix[i][j]=='' )
  25. {
  26. l_most[j] = std::max(l_most[j], l_curr);
  27. }
  28. else
  29. {
  30. l_most[j] = ;
  31. l_curr = j+;
  32. }
  33. }
  34. // from right to left
  35. for ( int j = COL-; j>=; --j )
  36. {
  37. if ( matrix[i][j]=='' )
  38. {
  39. r_most[j] = std::min(r_most[j], r_curr);
  40. }
  41. else
  42. {
  43. r_most[j] = COL-;
  44. r_curr = j-;
  45. }
  46. }
  47. // calculate area of rectangle
  48. for ( int j = ; j<COL; ++j )
  49. {
  50. max_area = std::max(max_area, (r_most[j]-l_most[j]+)*height[j]);
  51. }
  52. }
  53. return max_area;
  54. }
  55. };

tips:

学习了网上的O(m×n)时间复杂度的解法。

这道题的路子类似于http://www.cnblogs.com/xbf9xbf/p/4499450.html

总体的思路如下:

每次遍历一行的元素,以这一行作为X轴;模仿largest rectangle in histogram这道题

大体思路如下,需要对largest rectangle in histogram这道题有比较深刻的理解

a) 计算每个点的当前高度

b) 计算当前高度下每个点能往左推到哪个位置

c) 计算当前高度下每个点能往右推到哪个位置

d) 遍历以当前行作为X轴可能获得的最大面积

a)~d)走完所有行,就可以获得最大的矩形面积

思路实在精妙,详细记录下思考每个环节的过程:

a) 如何计算当前点的高度?

利用滚动数组技巧:height[j]记录的是到i-1行该列对应的高度;如果matrix[i][j]=='1',则height[j] += 1,即比上一行该列位置+1;如果matrix[i][j]=='0'则对于第i行来说,该列对应的高度就是0。这个道理比较直观,简单说就是滚动数组height[j]的更新原则是看高度能不能在新的一行续上。这种滚动数组技巧的好处在于只需要维护一个一维数组,否则需要维护二维数组,是dp过程的常用技巧。

b) c) 如何找每个点向左(右)能推到的最远的位置?

这个部分更是精妙,不仅利用了滚动数组的技巧,而且还充分利用了上一轮dp的结果。以b)为例分析,c)同理。

在此题的背景下,当前行的某列能向左推到哪要考虑如下几种情况:

  1)高度是是0(即matrix[i][j]=='1'不成立):显然能推到最左侧即0的位置,不受上一行该列能向左推到哪的影响。

  2)如果高度不是0(即matrix[i][j]=='1'成立),则这当前行该列能向左推到哪取决于左侧第一个不比它高的列在哪?

    考虑一个问题:在matrix[i][j]=='1'的前提下,第i行的l_most[j]可不可能比第i-1行的l_most[j]还小(即还往左)?

    显然,这是不可能的。因为第i行的j列已经把高度续上了,当且仅当第i行l_most[j]~j列的位置都满足高度续上的前提下,第i行的l_most[j]才可能等于第i-1行的l_most[j];一旦第i行l_most[j]~j有一个位置没有续上高度,那么第i行的l_most[j]就要比第i-1行的l_most[j]小了.

   通过以上分析,在第i行j列已经把高度续上的前提下,能向左推到哪,关键取决于在j左边且最靠近j列没续上高度的列,是否影响到了l_most[j]~j。因此,维护一个l_curr,标记到当前列为止,续上高度的列最多可能向左推到哪。

   所以,需要比较l_most[j]与l_curr的位置。如果遇上了高度为0的,则自动把l_curr+1;如果高度不为0的,判断l_curr是否影响到了l_most[j]

   描述的比较绕口,但是客观上也就是这样了。

d) 计算可能的最大高度

这个就是个常规的dp,不再赘述了。注意一点就是(right-left+1)*height,这里是否“+1”取决于l_most和r_most的取值方式。

==============================================

第二次过这道题,思路记得比较清晰;具体操作上一些细节再熟练一下。

  1. class Solution {
  2. public:
  3. int maximalRectangle(vector<vector<char> >& matrix)
  4. {
  5. int ret = ;
  6. if ( matrix.empty() ) return ret;
  7. vector<int> height(matrix[].size(), );
  8. for ( int i=; i<matrix.size(); ++i )
  9. {
  10. // update height
  11. for ( int j=; j<matrix[i].size(); ++j )
  12. {
  13. height[j] = matrix[i][j]=='' ? : height[j]+;
  14. }
  15. // update max area
  16. ret = max(ret, Solution::maxArea(height));
  17. }
  18. return ret;
  19. }
  20. static int maxArea(vector<int>& height)
  21. {
  22. int ret = ;
  23. height.push_back();
  24. stack<int> sta;
  25. for ( int i=; i<height.size(); ++i )
  26. {
  27. if ( sta.empty() || height[i]>height[sta.top()] )
  28. {
  29. sta.push(i);
  30. continue;
  31. }
  32. while ( !sta.empty() && height[sta.top()]>=height[i] )
  33. {
  34. int tmp = sta.top();
  35. sta.pop();
  36. if ( sta.empty() )
  37. {
  38. ret = max( ret, i*height[tmp] );
  39. }
  40. else
  41. {
  42. ret = max(ret, (i-sta.top()-)*height[tmp] );
  43. }
  44. }
  45. sta.push(i);
  46. }
  47. height.pop_back();
  48. return ret;
  49. }
  50. };

【Maximal Rectangle】cpp的更多相关文章

  1. hdu 4739【位运算】.cpp

    题意: 给出n个地雷所在位置,正好能够组成正方形的地雷就可以拿走..为了简化题目,只考虑平行于横轴的正方形.. 问最多可以拿走多少个正方形.. 思路: 先找出可以组成正方形的地雷组合cnt个.. 然后 ...

  2. Hdu 4734 【数位DP】.cpp

    题意: 我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+...a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字. 题目给出a,b,求出0~ ...

  3. 【Valid Sudoku】cpp

    题目: Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could ...

  4. 【Permutations II】cpp

    题目: Given a collection of numbers that might contain duplicates, return all possible unique permutat ...

  5. 【Subsets II】cpp

    题目: Given a collection of integers that might contain duplicates, nums, return all possible subsets. ...

  6. 【Sort Colors】cpp

    题目: Given an array with n objects colored red, white or blue, sort them so that objects of the same ...

  7. 【Sort List】cpp

    题目: Sort a linked list in O(n log n) time using constant space complexity. 代码: /** * Definition for ...

  8. 【Path Sum】cpp

    题目: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up ...

  9. 【Symmetric Tree】cpp

    题目: Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). F ...

随机推荐

  1. js addEventListener调用传参函数

    先看这段代码 function abc(key){ console.log(key); } for(let i=0;i<oInput.length;i++){ oInput[i].addEven ...

  2. 零基础逆向工程26_C++_03_Vector

    1 Vector 核心代码 #define SUCCESS 1 // 成功 #define ERROR -1 // 失败 #define MALLOC_ERROR -2 // 申请内存失败 #defi ...

  3. 怎么旋转PDF文件的方向并保存成功

    http://jingyan.baidu.com/article/59a015e39d7802f79488651e.html PDF格式的文档是非常普遍的一种阅读电子书格式,基本上非常好用了,不过有时 ...

  4. LeetCode OJ 3Sum 3个整数之和

    题意:给一个vector<int>容器,要求每当找到3个元素之和为0时就将这3个数按大小顺序记下来,用一个二维vector返回.也就是vector< vector<int> ...

  5. pat乙级1049

    浮点型乘整型和整型乘浮点型结果不同,不知为什么. double sum = 0.0; ; i < n; i++) { cin >> a[i]; sum += a[i] * (i + ...

  6. VMware安装win7系统

    1.创建一个虚拟机 2.配置iso映射文件   3.设置boot设置第一启动为cd   4.快速分区后重启电脑,然后选择[A]安装win7.  重启电脑后安装win7系统   搞定...  

  7. python剑指offer 实现树的子结构

    题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) # -*- coding:utf-8 -*- # class TreeNode: # def __ ...

  8. python_38_try-except异常处理语句及raise的使用

    # i=10 # print(30/(i-10)) # #程序将会出现以下报错信息 # # Traceback (most recent call last): # # File "C:/U ...

  9. 如何让图片相对于上层DIV始终保持水平、垂直都居中

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. 配置dubbo架构的maven项目

    1. 拆分工程 1)将表现层工程独立出来: e3-manager-web 2)将原来的e3-manager改为如下结构 e3-manager |--e3-manager-dao |--e3-manag ...