問題描述
給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度爲 1 。
求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。
以上是柱狀圖的示例,其中每個柱子的寬度爲 1,給定的高度爲 [2,1,5,6,2,3]
。
圖中陰影部分爲所能勾勒出的最大矩形面積,其面積爲 10 個單位。
示例:
輸入: [2,1,5,6,2,3]
輸出: 10
解題報告
維持一個 單調遞增棧
,當前元素小於棧頂元素時,以棧頂元素爲高度的矩形就無法向右邊擴展了,所以就可以計算以棧頂元素爲高度的最大矩形面積。
當然了,這題還有一些編程的技巧性,即設置 哨兵
。這樣做有什麼好處呢?
- 因爲在求以棧頂元素爲高度的最大矩形時,右邊界是當前元素的索引,左邊界是棧頂元素的上一個元素,爲什麼是棧頂元素的上一個元素,因爲當出現
[3, 6, 7, 4, 2]
這樣的柱狀圖,遍歷到4
時,會陸續計算以7
和6
爲高度的最大矩形面積,然後將4
壓棧,但是在計算以4
爲高度的最大矩形面積時,右邊界是4
, 這時左邊界爲0
, 而不是3
。但是這樣就會帶來一個問題,當棧中只剩下一個元素時,左邊界應該爲該元素的前一個元素, 即爲0
,與棧中只剩一下元素矛盾,除非特殊處理,爲了統一處理,在棧中加入哨兵 0
。 - 當遍歷到最後一個元素,以最後一個元素爲高度的最大矩形面積不好確定右邊界,爲了統一處理,在原始數組的末尾加入
哨兵 0
。
實現代碼
class Solution{
public:
int largestRectangleArea(vector<int>& heights)
{
int ans = 0;
stack<int> stk;
stk.push(0);
heights.insert(heights.begin(), 0);
heights.push_back(0);
for (int i = 1; i < heights.size(); i++)
{
// 每當遇到棧頂元素大於當前元素時,以棧頂元素爲高度的矩形必定不能向右擴展
// 所以當前需要先計算以棧頂元素爲高度的矩形高度
while (heights[stk.top()] > heights[i])
{
int cur = stk.top();
stk.pop();
ans=max(ans, heights[cur]*(i-stk.top()-1));
}
stk.push(i);
}
return ans;
}
};
$^{[2]}$
參考資料
[1] Leetcode 84. 柱狀圖中最大的矩形
[2] 題解區:Ikaruga