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)