题目详述
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
解法一
暴力法。时间复杂度:O(n^3),空间复杂度:O(1)
class Solution {
public int largestRectangleArea(int[] heights) {
int maxArea = 0;
for (int i = 0; i < heights.length; i++) {
for (int j = i; j < heights.length; j++) {
int minHeight = Integer.MAX_VALUE;
for (int n = i; n <= j; n++)
minHeight = Math.min(minHeight, heights[n]);
maxArea = Math.max(maxArea, minHeight * (j - i + 1));
}
}
return maxArea;
}
}
解法二
暴力优化法。时间复杂度O(n^2),空间复杂度O(1)
class Solution {
public int largestRectangleArea(int[] heights) {
int maxArea = 0;
for (int i = 0; i < heights.length; i++) {
int minHeight = Integer.MAX_VALUE;
for (int j = i; j < heights.length; j++) {
minHeight = Math.min(minHeight, heights[j]);
maxArea = Math.max(maxArea, minHeight * (j - i + 1));
}
}
return maxArea;
}
}
解法三
栈。 时间复杂度O(n),空间复杂度(n)
注意:
- 栈内存储的是下标,下标所代表的柱状高度始终是从小到大,若大于栈顶元素则入栈,小于栈顶元素则确定了最大矩形面积的高(当前矩形高度)和右边界,左边界则是栈顶元素的下一个元素。
- 所有高度下标均入栈后,再逐一出栈。
手跑程序:假设heights[6,7,5,2,4,5,9,3]
i = 0
push(0)
i = 1, 6 >= 7 不成立
push(1)
i= 2, 7 >= 5 pop(1) maxArea = 7 * (2 - 0 -1) = 7
6 >= 5 pop(0) maxArea = 6 * (2- (-1) - 1) = 12
push(2)
i = 3, 5 >=2 pop(2) maxArea = 5 * (3 - (-1) - 1) = 15
push(3)
i = 4, 2 >=4 不成立
push(4)
i = 5, 4 >= 5 不成立
push(5)
i = 6, 5 >= 9 不成立
push(6)
i = 7, 9 >=3 pop(6) maxArea = 9 * (7 - 5 - 1) = 9
5 >=3 pop(5) maxArea = 5 * (7 - 4 - 1) = 10
4 >= 3 pop(4) maxArea = 4 * (7 - 3 - 1)= 12
2 >= 3 不成立
push(7)
i = 8, 跳出for循环,进入while循环
maxArea = 3 * (8 - 3 - 1) = 12
maxArea = 2 * (8 - (-1) - 1) = 16
所以面积最大值是16
class Solution {
public int largestRectangleArea(int[] heights) {
int maxArea = 0;
Stack<Integer> stack = new Stack<>();
stack.push(-1);
for (int i = 0; i < heights.length; i++) {
while (stack.peek() != -1 && heights[stack.peek()] >= heights[i])
maxArea = Math.max(maxArea,
heights[stack.pop()] * (i - stack.peek() - 1));
stack.push(i);
}
while (stack.peek() != -1)
maxArea = Math.max(maxArea, heights[stack.pop()] * (heights.length - stack.peek() -1));
return maxArea;
}
}