Hard
题目描述
给定一个整数数组 heights ,表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:
输入:heights = [2,4]
输出:4
提示:
- 1 <= heights.length <= 10^5
- 0 <= heights[i] <= 10^4
解题思路
解题思路
这是一道经典的单调栈问题。核心思想是对于每个柱子,找到以它为高度的最大矩形面积。
暴力解法思路
对每个位置 i,向左右扩展找到第一个高度小于 heights[i] 的位置,计算以 heights[i] 为高度的矩形面积。时间复杂度 O(n²)。
单调栈优化思路(推荐)
使用单调递增栈来高效找到每个柱子左右两侧第一个更矮的柱子:
- 栈的作用:维护一个单调递增的柱子索引栈
- 入栈时机:当前柱子高度 >= 栈顶柱子高度时入栈
- 出栈计算:当前柱子高度 < 栈顶柱子高度时,说明找到了栈顶柱子的右边界,开始计算面积
- 左右边界:
- 右边界:当前位置 i
- 左边界:栈顶下一个元素(如果栈空则为 -1)
- 宽度 = i - left - 1
- 面积 = height * width
技巧优化
在数组末尾添加高度为 0 的柱子,确保所有柱子都能被处理到。
时间复杂度 O(n),空间复杂度 O(n),每个元素最多入栈出栈一次。
代码实现
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
stack<int> st;
heights.push_back(0); // 添加哨兵,确保所有柱子都被处理
int maxArea = 0;
for (int i = 0; i < heights.size(); i++) {
while (!st.empty() && heights[i] < heights[st.top()]) {
int h = heights[st.top()];
st.pop();
int w = st.empty() ? i : i - st.top() - 1;
maxArea = max(maxArea, h * w);
}
st.push(i);
}
return maxArea;
}
};
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
stack = []
heights.append(0) # 添加哨兵,确保所有柱子都被处理
max_area = 0
for i in range(len(heights)):
while stack and heights[i] < heights[stack[-1]]:
h = heights[stack.pop()]
w = i if not stack else i - stack[-1] - 1
max_area = max(max_area, h * w)
stack.append(i)
return max_area
public class Solution {
public int LargestRectangleArea(int[] heights) {
Stack<int> stack = new Stack<int>();
Array.Resize(ref heights, heights.Length + 1); // 添加哨兵
heights[heights.Length - 1] = 0;
int maxArea = 0;
for (int i = 0; i < heights.Length; i++) {
while (stack.Count > 0 && heights[i] < heights[stack.Peek()]) {
int h = heights[stack.Pop()];
int w = stack.Count == 0 ? i : i - stack.Peek() - 1;
maxArea = Math.Max(maxArea, h * w);
}
stack.Push(i);
}
return maxArea;
}
}
var largestRectangleArea = function(heights) {
let stack = [];
let maxArea = 0;
for (let i = 0; i <= heights.length; i++) {
let currentHeight = i === heights.length ? 0 : heights[i];
while (stack.length > 0 && heights[stack[stack.length - 1]] > currentHeight) {
let height = heights[stack.pop()];
let width = stack.length === 0 ? i : i - stack[stack.length - 1] - 1;
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
return maxArea;
};
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 暴力解法 | O(n²) | O(1) |
| 单调栈(推荐) | O(n) | O(n) |
相关题目
. Maximal Rectangle (Hard)