Leetcode个题解85

LEETCODE专题


85. Maximal Rectangle

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

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


问题:

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

分析:

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

    [0, 0, 1, 1, 1
    0, 0, 1, 1, 1
    0, 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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章