Leetcode个题解85

来源:互联网 发布:淘宝美工面试作品 编辑:程序博客网 时间:2024/06/05 02:57

LEETCODE专题


85. Maximal Rectangle

题目要求:
这里写图片描述

在一个矩阵中找到所有全为’1’的方形区域的面积并求出最大值。


问题:

  1. 如何得出这些区域?
  2. 如何求出这些区域的面积?

分析:

  1. 如果大家都被笔者带入去思考第一个问题的话,那么恭喜你,中了本题最大的坑当中了(@_@)。当然对于一些高手来说,这样做也是没有问题的。但是笔者要在这里介绍一下另一种方法,这来自于Leetcode的discussion板块的贡献者morrischen2008大神。
    这里要先纠正一下刚刚被笔者带入坑的各位朋友——其实我们根本不用费力去求这些区域,我们只需要记住当前的“最左边界值”、“最右边界值”以及高度即可。这里有关边界值的描述加了引号,是因为这不一定是最左或者最右的,举个例子:

    [0, 0, 1, 1, 10, 0, 1, 1, 10, 1, 1, 1, 1]

    我们从0开始计数。这个时候点(2, 2)的最左边界值就应该为2而非1,如果为1的话高度就会减少。而我们针对这种情况可以采用点[2, 1]最右边界值来参与计算包含该点的矩形,结果为4,即使它不是最大的面积。

有了这一个思路之后,我们就可以来设计这个算法啦。

  1. 最左边界值的选取。我们可以让每一行每个元素都有这个属性,且这个属性可以继承自上一行的元素的最左边界值。在计算该行最左边界值时,再加入一个参数curLeft,也就是当前未出现0的最左边界值(这里的最左边界值则是真的最左边界值,为了区分,我们用left2表示该值,用left1表示要计算的最左边界值,最右边界值也采用这种方法加以区分),参与计算。在left1和left2之间选取一个最大值作为该点的最左边界值,以保留上一行的高度。
    计算顺序:从左到右。
  2. 最右边界值的选取。除了加入的参数为curRight,且计算的时候选取的是right1与right2的最大值之外,其他的与最左边界值选取过程一致。
    计算顺序:从右到左。
  3. 高度值height选取。高度是一个积累过程,如果有连续的’1’则累加,遇到’0’则清零。
  4. 面积的计算。有了以上的基础,我们就可以用简单的公式来计算矩形的面积啦。公式就是(right - left) * height。
  5. 去最大的面积,也就是再将每个面积都比较一下。方法有很多,具体就不再赘述了。

下面直接上代码:

class Solution {public:    int max(int a, int b) {        return a > b ? a : b;    }    int min(int a, int b) {        return a < b ? a : b;    }    int maximalRectangle(vector<vector<char>>& matrix) {        /*         * every item saves its leftest bound, its rightest bound and its height         * 1. whenever its char is '0', the cumulative height will be 0         * 2. the rightest bound of each factor is initialed to be the largest value         *    and calculated from right to left, with the value of minimum of         *    curRight and the rightest bound of the last row.         * 3. the leftest bound of each factor is initialed to be the smallest value         *    and calculated from left to right, with the value of maximum of         *    curLeft and the leftest bound of the last row.         */        int row = matrix.size();        if (row == 0) return 0;        int col = matrix[0].size();        if (col == 0) return 0;        int r, c;        vector<int> left(col, 0);        vector<int> right(col, col);        vector<int> height(col, 0);        int maxArea = 0;        for (r = 0; r < row; r++) {            int curLeft = 0;            int curRight = col;            for (c = 0; c < col; c++) {                if (matrix[r][c] == '1') {                    left[c] = max(left[c], curLeft);                    height[c]++;                } else {                    left[c] = 0;                    curLeft = c + 1;                    height[c] = 0;                }            }            for (c = col - 1; c >= 0; c--) {                if (matrix[r][c] == '1') {                    right[c] = min(right[c], curRight);                } else {                    right[c] = col;                    curRight = c;                }                maxArea = max(maxArea, (right[c] - left[c]) * height[c]);            }        }        return maxArea;    }};

时间复杂度:O(n)