84.柱状图中最大的矩形
暴力解法
以每一个柱子为基准,都去找左边比它矮的 右边比它矮的,这样就确定了它的宽,再用这个柱子的高去 乘以 它的 宽,就能算出来 在这个柱状图中,它所能形成的 矩形面积,最后选一个最大的
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
// 暴力解法
int maxArea = heights[0];
for (int i = 0; i < heights.size(); i++) {
int l = -1;
int r = heights.size();
for (int j = i - 1; j >= 0; j--) {
if (heights[j] < heights[i]) {
l = j;
break;
}
}
for (int j = i + 1; j < heights.size(); j++) {
if (heights[j] < heights[i]) {
r = j;
break;
}
}
maxArea = max(maxArea, heights[i] * (r - l - 1));
}
return maxArea;
}
};
双指针优化
定义两个数组 存储每个柱子的 左右比它矮的下标,在遍历的时候,
记录左边比它矮的下标, 从 左到右遍历, 记录的时候利用 之前记录过的值
记录右边比它矮的下标,从 右到左遍历,记录的时候 利用 之前记录过大值。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
// 双指针解法
// 需要记录每个柱子 左边 比它小的下标 以及右边比它小的下标
vector<int> minLeftIndex(heights.size());
vector<int> minRightIndex(heights.size());
// 先记录左边,从前往后遍历
minLeftIndex[0] = -1; // 避免下面出现死循环
for (int i = 0; i < heights.size(); i++) {
int l = i - 1;
while (l >= 0 && heights[l] >= heights[i]) l = minLeftIndex[l];
minLeftIndex[i] = l;
}
// 再记录右边, 从后往前比哪里
minRightIndex[heights.size() - 1] = heights.size(); // 防止下面出现死循环
for (int i = heights.size() - 1; i >= 0; i--) {
int r = i + 1;
while (r < heights.size() && heights[r] >= heights[i]) r = minRightIndex[r];
minRightIndex[i] = r;
}
// 再计算最大面积
int maxArea = 0;
for (int i = 0; i < heights.size(); i++) {
int w = minRightIndex[i] - minLeftIndex[i] - 1;
maxArea = max(maxArea, w * heights[i]);
}
return maxArea;
}
};
单调栈
和 42.接雨水 类似,需要注意的是 该题 求得是 比中间柱子矮的, 需要单调递减, 同时首尾需要加上 0;
首 加上 0:以 柱形元素为[8, 6, 4, 2]为例,6 比 8 小,需要弹栈,此时只有 mid 和 right,缺少 left
尾 加上 0:以 柱形元素为[2, 4, 6, 8]为例,将会把所有元素全部入栈,没有计算过程,因此 尾巴加上 0, 进行计算。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
// 单调栈
stack<int> st;
heights.insert(heights.begin(), 0);
heights.insert(heights.end(), 0);
int maxArea = 0;
for (int i = 0; i < heights.size(); i++) {
while(!st.empty() && heights[i] < heights[st.top()]) {
int mid = st.top();
st.pop();
if (!st.empty()) {
int r = i;
int l = st.top();
int w = r - l - 1;
maxArea = max(maxArea, w * heights[mid]);
}
}
st.push(i);
}
return maxArea;
}
};