[【单调栈】柱状图中最大的矩形
题目描述
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。(leetcode 84)
提示:以下是本篇文章正文内容,下面案例可供参考
一、示例
二、求解方法
1.枚举宽度暴力遍历
枚举宽度的思想是对固定宽度为w的宽度,找到最低的高度,然后宽×高就是一种方案,然后遍历取最大的方案就可以了,时间复杂度为O(n^2), 结果会超时。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
int ans = 0;
for (int l=0; l<n; l++){
int minheight = INT_MAX;
for (int r=l; r<n; r++){
minheight = min(minheight, heights[r]);
ans = max(ans, minheight*(r-l+1));
}
}
return ans;
}
};
2.枚举高度暴力遍历
枚举高度的思想是,从左到右遍历每一个高度,然后当前遍历到的高度向两端搜索,两边延伸直到高度小于当前的高度,记下此时的宽度,然后宽×高,遍历时记下最大值。会超时
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
int ans = 0;
for (int i=0; i<n;i++){
int left = i;
int right = i;
while (left>0 && heights[left-1]>=heights[i]){
left--;
}
while (right<n-1&&heights[right+1]>=heights[i]){
right++;
}
ans = max(ans, (right-left+1)*heights[i]);
}
return ans;
}
};
3.单调栈
首先单调栈的思想是在遍历过程中维护栈内数据的单调性,那么这道题为什么会和单调栈扯上关系呢?
按照遍历高度,对于两根柱子j0以及j1,如果j0<j1,并且heights[j0]>=heights[j1],那么后面的柱子i向左找小于其高度的柱子时,j1会挡住j0,j0就不会作为答案了。所以此时只需要单调顺序加入栈,当不满足heights[j0]>=heights[j1]时候,开始搜索栈内能够得到的最大面积,由于栈内是单调的,因此计算当前出栈元素的面积时的宽度为(i-下一个出栈元素的下标-1),这里选择下一个出栈元素的作为下标原因是,因为栈一值都是在维护一个单调的情况,在碰到不单调时让不满足单调性的元素出栈,因此下一个出栈元素的下标到i之间记录了均满足大于等于这样高度的元素,-1是因为两端不能取。通过这样遍历后可以得到不在栈堆记录下表里的最大值。然后根据类似的规则处理,假设最后下表+1位置的高度为0,处理栈中的元素直到栈为空,得到最终的最大值。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
unsigned long n = heights.size();
if (n==1){
return heights[n-1];
}
stack<int> stk;
stk.push(0);
int ans = 0;
for (int i=1; i<heights.size(); i++){
while(!stk.empty() && heights[i]<heights[stk.top()]){
int w = i;
int h = heights[stk.top()];
stk.pop();
if (!stk.empty()){
w = i-stk.top()-1;
}
ans = max(ans, h*w);
}
stk.push(i);
}
while (!stk.empty()){
int h = heights[stk.top()];
stk.pop();
int w = n;
if (!stk.empty()) w = n-stk.top()-1;
ans = max(ans, h*w);
}
return ans;
}
};