暴力超时,明天就做单调栈
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
//最大=最优解≈dp
/*if(heights.size() == 0) return 0;
int maxArea = INT_MIN;
for(int i = 0;i<heights.size();++i){
int left = i, right = i;
while(left-1 >= 0 && heights[left-1] >= heights[i]) left--;
while(right+1 <= heights.size()-1 && heights[right+1] >= heights[i]) right++;
maxArea = max((right-left+1)*heights[i],maxArea);
}
return maxArea;*/
//因为要找到左右两边第一个比自己小的,所以维护一个单调栈便可以在O(n)的时复下找到左右两边比自己小的,自身这个元素下面记录着左边第一个比自己小的元素,而遍历时可以得到右边第一个比自己小的元素,因为要求宽度,所以栈里记录的是下标
stack<int> sta;
//如果当前遍历到的柱子小于栈顶,就证明找到了
//防止所有柱子都是单调递增的
heights.push_back(0);
int maxArea = 0;
for(int i = 0; i < heights.size(); ++i){
while(!sta.empty() && heights[sta.top()] > heights[i]){
int top = sta.top();
sta.pop();
//以栈顶柱子为高,宽为右-左-1,但是左边有可能没有值,左边没有值证明它是从0一直到i的,所以宽度是i
maxArea = max(maxArea, heights[top]*(sta.empty()?i:(i-sta.top()-1)));
}
sta.push(i);
}
return maxArea;
}
};
细节满满的题,不仅要知道单调栈现在在做什么,更要考虑多种情况。比如数组本身单调递增,或者sta为空的情况。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
//单调递增栈,因为我们要找的是当前柱子左右第一个小于自身的柱子
//左边的柱子就是弹出栈顶后的新栈顶,右边的柱子就是新遍历到的这个柱子
//其实单调栈的目的就是找出以每个栈顶往左右发散的宽度,发散到比自己小的就不能发散了
//有可能是单调递增的数组,比如123这样的数组,那么就永远找不到右边比自己小的数字
//所以我们要在最后加上一个0,不会影响结果
stack<int> sta;
heights.push_back(0);
int res = 0;
for(int i = 0; i < heights.size(); ++i){
while(!sta.empty() && heights[sta.top()] > heights[i]){
int top = sta.top();
sta.pop();
//左边要注意,有可能弹出后栈是空的了,代表从0开始到当前判断的栈顶,没有一个数字比自己小,就当作都比自己大好了,那么宽就是i-0
res = max(res,heights[top]*(sta.empty()?i:(i-sta.top()-1)));
}
sta.push(i);
}
return res;
}
};