难度:困难。
标签:栈,数组。
没想到方法,看了标签,知道应该是单调栈,试了一下,结果是错的。单调栈这部分很不熟悉啊。
看题解。
枚举每一根柱子,以柱子
i
i
i的高度
h
e
i
g
h
t
i
height_i
heighti为高构成的矩形,则其宽由i左右两边第一个小于
h
e
i
g
h
t
i
height_i
heighti的柱子的位置决定的。因此找柱子
i
i
i的左右两边第一个小于其高度的柱子的位置。
用
l
e
f
t
[
i
]
left[i]
left[i]表示左边第一个小于
h
e
i
g
h
t
i
height_i
heighti的柱子的索引,用
r
i
g
h
t
[
i
]
right[i]
right[i]表示右边第一个小于
h
e
i
g
h
t
i
height_i
heighti的柱子的索引。
这两个问题可以分别用单调栈来求。
然后,单调栈具体的操作没怎么看题解,自己想出来的。
正确解法:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
stack<int> stk;
vector<int> left(n), right(n);
for(int i = 0; i < n; ++i){
while(!stk.empty() && heights[stk.top()] >= heights[i]){
stk.pop();
}
if(stk.empty())left[i] = -1;
else left[i] = stk.top();
stk.push(i);
}
stk = stack<int>();
for(int i = n - 1; i >= 0; --i){
while(!stk.empty() && heights[stk.top()] >= heights[i]){
stk.pop();
}
if(stk.empty())right[i] = n;
else right[i] = stk.top();
stk.push(i);
}
int res = heights[0];
for(int i = 0; i < n; i++){
res = max(res, heights[i] * (right[i] - left[i] - 1));
}
return res;
}
};
结果:
可以进一步进行优化,对栈遍历一次可以同时求解出left和right数组。
在求left过程中,对柱子
i
i
i进行出栈时,当前柱子即为
r
i
g
h
t
[
i
]
right[i]
right[i]的结果。因此,一次即可求出两个结果。
需要提前将right数组用n进行初始化,这样,最终没有弹出栈的元素说明他们对应的right为n。
正确解法:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
stack<int> stk;
vector<int> left(n), right(n, n);
for(int i = 0; i < n; ++i){
while(!stk.empty() && heights[stk.top()] >= heights[i]){
right[stk.top()] = i;
stk.pop();
}
if(stk.empty())left[i] = -1;
else left[i] = stk.top();
stk.push(i);
}
int res = heights[0];
for(int i = 0; i < n; i++){
res = max(res, heights[i] * (right[i] - left[i] - 1));
}
return res;
}
};
结果: