题目:
给定 n
个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1
。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例:
- 输入: h e i g h t s = [ 2 , 1 , 5 , 6 , 2 , 3 ] heights = [2,1,5,6,2,3] heights=[2,1,5,6,2,3]
- 输出: 10 10 10
- 解释: 最大的矩形为图中红色区域,面积为 10。
解题思路:暴力双指针
遍历数组heights
中的每根柱子,然后遍历左右两侧大于该柱子的最边缘侧柱子,找到其下标,然后计算宽度,为right - left - 1
,高度为当前柱子高度height[i]
,然后记录max(sum, h * w)
找到最大的矩形面积。不过时间复杂度是
O
(
n
2
)
O(n^2)
O(n2),会超时。接下来进行优化。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int sum = 0;
for(int i = 0; i < heights.size(); i++){
int left = i;
int right = i;
for(; left >= 0; left--){
if(heights[left] < heights[i]) break;
}
for(; right < heights.size(); right++){
if(heights[right] < heights[i]) break;
}
int w = right - left - 1;
int h = heights[i];
sum = max(h * w, sum);
}
return sum;
}
};
解题思路二:双指针优化
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
vector<int> minLeftIndex(heights.size());
vector<int> minRightIndex(heights.size());
int size = heights.size();
// 记录每个柱子 左边第一个小于该柱子的下标
minLeftIndex[0] = -1; // 注意这里初始化,防止下面while死循环
for (int i = 1; i < size; i++) {
int t = i - 1;
// 这里不是用if,而是不断向左寻找的过程
while (t >= 0 && heights[t] >= heights[i]) t = minLeftIndex[t];
minLeftIndex[i] = t;
}
// 记录每个柱子 右边第一个小于该柱子的下标
minRightIndex[size - 1] = size; // 注意这里初始化,防止下面while死循环
for (int i = size - 2; i >= 0; i--) {
int t = i + 1;
// 这里不是用if,而是不断向右寻找的过程
while (t < size && heights[t] >= heights[i]) t = minRightIndex[t];
minRightIndex[i] = t;
}
// 求和
int result = 0;
for (int i = 0; i < size; i++) {
int sum = heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1);
result = max(sum, result);
}
return result;
}
};