目录
题目链接:84.柱状图中最大的矩形
思路
双指针:记录每个柱子左边第一个小于该柱子的下标,而不是左边第一个小于该柱子的高度。
单调栈:本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序!
代码
双指针
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int len = heights.size();
if (len == 1)
return heights[0];
vector<int> left(len); // 记录每个柱子左边第一个比自己大的下标
vector<int> right(len); // 记录每个柱子右边第一个比自己大的下标
left[0] = -1;
for (int i = 1; i < len; i++) {
int t = i - 1;
while (t > 0 && heights[t] >= heights[i]) {
t = left[t];
}
left[i] = t;
}
right[len - 1] = len;
for (int i = len - 2; i >= 0; i--) {
int t = i + 1;
while (t < len && heights[t] >= heights[i]) {
t = right[t];
}
right[i] = t;
}
int result = 0; // 记录最大面积
for (int i = 0; i < len; i++) {
int sum = heights[i] * (right[i] - left[i] - 1);
result = max(result, sum);
}
return result;
}
};
单调栈
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int result = 0;
stack<int> st;
// 首尾添0
heights.insert(heights.begin(), 0);
heights.push_back(0);
st.push(0);
for (int i = 1; i < heights.size(); i++) {
if (heights[i] > heights[st.top()]) {
st.push(i);
} else if (heights[i] == heights[st.top()]) {
st.pop();
st.push(i);
} else {
while (!st.empty() && heights[i] < heights[st.top()]) {
int mid = st.top();//记录中间
st.pop();//然后弹出
if (!st.empty()) {
int left = st.top();
int right = i;
int h = heights[mid];
int w = right - left - 1;
result = max(h * w, result);
}
}
st.push(i);
}
}
return result;
}
};
总结:
①与接雨水不同的是这里求柱子凸出来的部分,而不是凹槽了,所以单调栈从栈头到栈底是从大到小的顺序,与接雨水恰恰相反
②感觉还是比接雨水复杂点,没理清思路,后面复习得好好看看
③两个月的算法练习结束了,从头到尾过了一遍经典题目,后面重要的是复习。一刷的时候有些问题完全解决,过了那么久前面的题也忘了