题目
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
思路1 暴力解法
遍历每一个高度,求每个高度的最大面积
在每个高度时,向左右遍历,获取它的左右边界,然后计算面积
class Solution { //暴力法,遍历每个高度 ,求最大面积
public int largestRectangleArea(int[] heights) {
int max = 0;
for (int i = 0; i < heights.length; i++) {
int h = heights[i];//高度
int j = i-1, k = i+1;//左右边界
while (j >= 0 && heights[j] >= heights[i]) { //得到左边界
j--;
}
while (k < heights.length && heights[k] >= heights[i]) { //得到右边界
k++;
}
int area = h * (k - j - 1);
max = Math.max(max,area);
}
return max;
}
}
复杂度分析
时间复杂度O(N^2),需要遍历每一个高度,在每个高度上向左右遍历它的左右边界
空间复杂度O(1)
思路二
使用栈,来存放每个高度和下标。栈里面的排序是从小到大的,每当放入高度小的,需要将栈内元素高度大的抛出,并计算面积。这样 每一个高度,它的左边界就是栈中它下面的元素,它的右边界,就是直到放入比它高度小的元素。直到所有高度都遍历完。
代码
class Solution {
class Node{ //定义结点类,放入的元素需要有高度和下标,这样方便计算面积
int height;
int place;
Node(int place, int height){
this.place = place;
this.height = height;
}
}
public int largestRectangleArea(int[] heights) {
int max = 0;
Stack<Node> stack = new Stack<>();
stack.push(new Node(-1,0)); //放入一个高度0,下标-1 的结点当做是哨兵
for(int i = 0; i < heights.length; i++) {
Node node = new Node(i,heights[i]);
while (node.height < stack.peek().height) { //遇到高度小于栈顶元素时,将栈内高度大的元素抛出,并计算面积。
int area = stack.pop().height * (node.place - stack.peek().place - 1);
max = Math.max(max,area);
}
stack.push(node);
}
while(stack.size() > 1) { //循环结束后,栈内还有元素,那么这些元素右边界一定是最右边的了
int area = stack.pop().height * (heights.length - stack.peek().place - 1);
max = Math.max(max,area);
}
return max;
}
}
复杂度分析
时间复杂度O(N),只需要遍历一遍数组的高度。
空间复杂度O(N),最坏情况,高度是从小到大,栈内要存放所有的高度。