LeetCode:84. Largest Rectangle in Histogram
題目:
Given n non-negative integers representing the histogram’s bar height
where the width of each bar is 1, find the area of largest rectangle
in the histogram.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].
The largest rectangle is shown in the shaded area, which has area = 10 unit.
題目大意就是給出一個柱狀圖的高度的陣列,求出其中能畫出的最大矩形的面積。
1.方法一
一個比較簡單暴力,容易理解的方法:對於每一個方柱,分別向左向右遍歷,到達第一個小於該方柱高度的方柱停止,此時畫出了一個以該方柱為最小高度的最大矩形,可以計算出面積:
class Solution { public: int largestRectangleArea(vector<int>& heights) { if (heights.empty()) return 0; int max = 0; for (int i = 0; i < heights.size(); ++i) { if (heights[i] <= max/heights.size()) continue;//如果該方柱高度過低,那也沒有計算的必要了,略過 int temp = helper(heights, i); if (temp > max) max = temp; } return max; } private: int helper(const vector<int>& heights, int i) { if (heights[i] == 0) return 0; int l = i, r = i; while(l-1 >= 0 && heights[l-1] >= heights[i]) --l; while(r+1 < heights.size() && heights[r+1] >= heights[i]) ++r; return heights[i] * (r-l+1); } };
2.方法二
解法來源:https://www.geeksforgeeks.org/largest-rectangle-under-histogram/
比較難以理解,但是該方法時間複雜度為O(N),值得思考。
方法是這樣的:還是要找出以每個方柱為最低高度的最大矩形,關鍵就是找出左邊第一個小於該高度的和右邊第一個小於該高度的。維持一個stack,遍歷輸入的陣列。如果當前遍歷的該方柱高度大於等於棧頂的方柱高度,那麼就將其壓入棧;如果當前遍歷的該方柱高度小於棧頂的方柱高度,就一直將棧頂元素彈出,直到該方柱高度大於等於棧頂的方柱高度。對於每個彈出的方柱,計算以它為最低高度的最大矩形的面積,計算的方法:彈出後當前棧頂的方柱是左邊第一個小於該高度的方柱,當前遍歷的方柱是右邊第一個小於該高度的方柱。
這是從左往右遍歷的。實際程式設計中,為了方便,往往在右邊放一個高度為0的方柱作為哨兵,然後從右往左遍歷。
光看文字描述比較難以理解,需要自己在草稿紙上舉一個例子,將整個過程模擬一遍,好好體會一下。
下面是我的程式碼:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
if (heights.empty())
return 0;
int max = 0;
heights.push_back(0);//作為哨兵
int N = heights.size();
stack<int> si;
si.push(N-1);
for (int i = N-2; i >= 0; --i) {
if (heights[i] >= heights[si.top()]) {
si.push(i);
continue;
}
while (heights[si.top()] > heights[i]) {
int t = si.top();
si.pop();
int s = heights[t] * (si.top()-i-1);
if (s > max)
max = s;
}
si.push(i);
}
while (si.size() > 1) {//遍歷結束後,將棧裡面殘留的元素彈出
int t = si.top();
si.pop();
int s = heights[t] * (si.top()-(-1)-1);
if (s > max)
max = s;
}
return max;
}
};