heights
,数组中的数字用来表示柱状图中各个柱子的高度。
1
。O(n^2)
,自然也最容易理解:
O(nlogn)
,对于该题来说分治解法也会超时,但是也值得理解,以下分析来自网友题解(图也来自该网友),这段讲解得很好,我懒得再自己整理了:
以 [2, 1, 5, 6, 2, 3]
为例,可以发现最短的矩形高度 1
的下标为 1
,那么最大面积矩形存在三种可能:
6
(图中绿色部分);left
部分);right
部分)。如图所示,确定数组的左右边界,便可以递归进入左边子数组和右边子数组了。
O(n)
,并且单调栈解法还存在普通方法和优化方法。
num = [2, 1, 5, 6, 2, 3]
为例子,假设维护一个栈,栈中存放索引,索引对应的元素单调递增;num[4] = 2
的时候,栈中元素为 stk = [0, 2, 3]
;stk.top() = 3
,且 2 < num[stk.top()]
,所以需要弹出栈顶,弹出前用临时值保存 tmp = stk.top() = 3
;stk = [0, 2]
,且 num[tmp = 3] = 6
、num[4] = 2
,则可以确定 6
的下一个更小值为 2
,同时可以确定 6
的前一个更小值为 num[stk.top()=2] = 2
;【从这里已经看出,单次遍历就可以找到前后更小值位置】num
尾部插入一个数值 0
,这样就保证了单调栈一次遍历结束后栈中不再存在元素(因为题目中提及,数组中只存在非负整数,所以当遇到这个 0
的时候,栈中所有元素都会被清空);该优化只是为了简化代码,并没有优化时间复杂度。class Solution
{
public:
int largestRectangleArea(vector<int>& heights)
{
int max = 0;
int left = 0;
int right = 0;
int m = heights.size();
for(int i =0;i<m;i++){
left = i-1;
right = i+1;
if(m * heights[i]>max){ // 关键在于此步判断
while(left>=0 && heights[left]>=heights[i]){
left--;
}
while(right<=m-1 && heights[right]>=heights[i]){
right++;
}
max = ::max(max,(right - left - 1)*heights[i]);
}
}
return max;
}
};
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
vector<int> left(n), right(n);
stack<int> mono_stack;
for (int i = 0; i < n; ++i) {
while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
mono_stack.pop();
}
left[i] = (mono_stack.empty() ? -1 : mono_stack.top());
mono_stack.push(i);
}
mono_stack = stack<int>();
for (int i = n - 1; i >= 0; --i) {
while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
mono_stack.pop();
}
right[i] = (mono_stack.empty() ? n : mono_stack.top());
mono_stack.push(i);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans = max(ans, (right[i] - left[i] - 1) * heights[i]);
}
return ans;
}
};
class Solution
{
public:
int largestRectangleArea(vector<int>& heights)
{
heights.emplace_back(0);// 加哨兵
stack<int> stk;
int ret = 0;
for(int i = 0; i < heights.size(); ++i)
{
while(!stk.empty() && heights[i] < heights[stk.top()])
{
int height = heights[stk.top()];
stk.pop();
ret = max(ret, height * (stk.empty() ? i : (i - stk.top() - 1)));
}
stk.push(i);
}
return ret;
}
};