84. 柱状图中最大的矩形 - 力扣(LeetCode)
单调栈求矩形面积系列:
LeetCode第 84 题:柱状图中最大的矩形(C++)_zj-CSDN博客
LeetCode第 85 题:最大矩形(C++)_zj-CSDN博客
LeetCode第 221 题:最大正方形(C++)_zj-CSDN博客
暴力法
考虑暴力法:遍历每根柱子,以当前柱子 i 的高度作为矩形的高,那么矩形宽度的左边界即为向左找到第一个高度小于当前柱体 i 的柱体,右边界即为向右找到第一个高度小于当前柱体 i 的柱体。对于每个柱子都计算一遍以当前柱子作为高的矩形面积,最终比较出最大的矩形面积:
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int res = 0, n = heights.size();
// 遍历每个柱子,以当前柱子的高度作为矩形的高 h,
// 从当前柱子向左右遍历,找到矩形的宽度 w。
for (int i = 0; i < n; i++) {
int w = 1, h = heights[i], j = i-1;//宽,高
//相当于以当前值为矩形高度,尽量向两边扩展宽
while (j >= 0 && heights[j--] >= h) w++;//宽向左增加1
j = i+1;
while (j < n && heights[j++] >= h) w++;//宽向右增加1
res = max(res, w * h);
}
return res;
}
};
最后的用例超时了,但是至少证明方法思路是对的。
单调栈
单调栈的思路,细节很多,画画图更好理解:暴力解法、栈(单调栈、哨兵技巧) - 柱状图中最大的矩形 - 力扣(LeetCode)
class Solution {
public:
int largestRectangleArea(vector<int>& heights){
int res = 0;
stack<int> stk;//单调栈,存储的是下标
//首尾添加哨兵
heights.insert(heights.begin(), 0);
heights.push_back(0);
for (int i = 0; i < heights.size(); i++){
while (!stk.empty() && heights[stk.top()] > heights[i]){//一定是while循环
int height = heights[stk.top()];//矩形高
stk.pop();
int width = i - stk.top() - 1;//矩形宽(建议画图进行辅助理解,这儿很容易出错)
res = max(res, height*width);
}
stk.push(i);
}
return res;
}
};
如果不适用哨兵(不在前后插入0):
class Solution {
public:
int largestRectangleArea(vector<int>& heights){
int res = 0;
stack<int> stk;//单调栈,存储的是下标
stk.push(-1);//为了方便计算(其实也算是哨兵)
for (int i = 0; i < heights.size(); i++){
while (stk.top() != -1 && heights[stk.top()] > heights[i]){
int height = heights[stk.top()];//矩形高
stk.pop();
int width = i - stk.top() - 1;//矩形宽
res = max(res, height*width);
}
stk.push(i);
}
while(stk.top() != -1){
int height = heights[stk.top()];
stk.pop();
int width = heights.size() - stk.top() - 1;
res = max(res, height*width);
}
return res;
}
};