LEETCODE专题
85. Maximal Rectangle
题目要求:
在一个矩阵中找到所有全为’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,即使它不是最大的面积。
有了这一个思路之后,我们就可以来设计这个算法啦。
- 最左边界值的选取。我们可以让每一行每个元素都有这个属性,且这个属性可以继承自上一行的元素的最左边界值。在计算该行最左边界值时,再加入一个参数curLeft,也就是当前未出现0的最左边界值(这里的最左边界值则是真的最左边界值,为了区分,我们用left2表示该值,用left1表示要计算的最左边界值,最右边界值也采用这种方法加以区分),参与计算。在left1和left2之间选取一个最大值作为该点的最左边界值,以保留上一行的高度。
计算顺序:从左到右。 - 最右边界值的选取。除了加入的参数为curRight,且计算的时候选取的是right1与right2的最大值之外,其他的与最左边界值选取过程一致。
计算顺序:从右到左。 - 高度值height选取。高度是一个积累过程,如果有连续的’1’则累加,遇到’0’则清零。
- 面积的计算。有了以上的基础,我们就可以用简单的公式来计算矩形的面积啦。公式就是(right - left) * height。
- 去最大的面积,也就是再将每个面积都比较一下。方法有很多,具体就不再赘述了。
下面直接上代码:
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)