問題描述:
給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度爲 1 。
求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。
以上是柱狀圖的示例,其中每個柱子的寬度爲 1,給定的高度爲 [2,1,5,6,2,3]。
圖中陰影部分爲所能勾勒出的最大矩形面積,其面積爲 10 個單位。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram
示例:
輸入: [2,1,5,6,2,3]
輸出: 10
解題思路:
1.暴力解法
給定左邊界,向右遍歷,依次找出最小高度,利用高*寬,取最大值
下面是具體代碼:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int res = 0;
for(int i=0;i<heights.size();i++){
int minheight = INT_MAX;
for(int j=i;j<heights.size();j++){
minheight = min(minheight,heights[j]);
res = max(res,minheight*(j-i+1));
}
}
return res;
}
};
暴力解法,有測試用例過不了
2.利用單調棧
先設想,當一次遍歷時,遍歷到i,我們需要向左找到第一個比height[i]小的,向右找到第一個比height[i]小的元素
這樣我們就可以求出了寬帶,高度爲height[i]取最大值
我們創建一個單調遞增棧
如果新的元素比棧頂元素大,就入棧
- 如果新的元素較小,那就一直把棧內元素彈出來,直到棧頂比新元素小
加入這樣一個規則之後,會有什麼效果
- 棧內的元素是遞增的
- 當元素出棧時,說明這個新元素是出棧元素向後找第一個比其小的元素
舉個例子,現在索引在 6 ,棧裏是 1 5 6 。
接下來新元素是 2 ,那麼 6 需要出棧。
當 6 出棧時,右邊 2 代表是 6 右邊第一個比 6 小的元素。
- 當元素出棧後,說明新棧頂元素是出棧元素向前找第一個比其小的元素
當 6 出棧時,5 成爲新的棧頂,那麼 5 就是 6 左邊第一個比 6 小的元素。
下面是完整代碼:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int res = 0;
//頭部和尾部插入0,是爲了方便計算邊界
heights.push_back(0);
heights.insert(heights.begin(),0);
stack<int> stk;
for(int i=0;i<heights.size();i++){
while(!stk.empty()&& heights[stk.top()]>heights[i]){
int top = stk.top();
stk.pop();
int left = stk.top()+1;
int right = i-1;
res = max(res,heights[top]*(right-left+1));
}
stk.push(i);
}
return res;
}
};