题解:给出的n个非负整数表示每个直方图的高度,每个直方图的宽均为1,在直方图中找到最大的矩形面积。
例子:给定数组: height = [2,1,5,6,2,3],返回 10 (5 * 2)
分析:总体来说首先很自然会想到暴力法解决,但是优化的方式不容易想到。自己看了网上的答案都特别抽象,看了一个多小时最后靠举例子才勉强明白怎么优化。
1、暴力法
首先,可以使用暴力破解法。以每一个数字作为高度,遍历找出左右可以匹配的最大长度。以i=2举例,左侧可以和height[2]=5组成矩形的索引为i=2本身;
右侧可以和height[2]=5组成矩形的索引为i=3;
所以对于i=2来说,最大面积就是10 (5 * 2)。
随后在不同i值对应得到的不同面积值中选出最大的一个即可。但是由于是O(n^2)复杂度,肯定过不了LeetCode的OJ,随后参照网上的过程进行优化处理。
2、栈
使用上面的例子不太方便讲解,我们在举一个例子height=[1,2,3,4,5],如下图所示:
首先,我们对数组进行扩充,height[6]=0,那么直方图变为下图;
需要用到一个栈stack,算法如下:
如果stack为空 或者 height[i] > height[stack.peek()],
那么将i的索引加入栈,并且i++;
否则,即height[i] <= height[stack.peek()]
那么出栈,然后计算对于当前i的最大面积。
i=0时,stack为空,stack.push(0);
i=1时,height[1] > height[0] ,stack.push(1);
i=2时,height[2] > height[1] ,stack.push(2);
i=3时,height[3] > height[2] ,stack.push(3);
i=4时,height[4] > height[3] ,stack.push(4);
i=5时,height[5] < height[4] ,t = stack.pop = 4,接下来的任务就是在寻找以t=4为右侧的矩形的最大面积,即:
sum = max(0, 1*5) = 5
t = stack.pop() = 3
sum = max(6, 2*4) = 8
t = stack.pop() = 2
sum = max(8, 3*3) = 9
t = stack.pop() = 1
sum = max(9, 4*2) = 9
stack.push(5) 注:此时height[5] > height[stack.pop()](即height[0])
i = i + 1 = 6
i=6时,height[6] < height[5] ,t = stack.pop = 5,接下来的任务就是在寻找以t=5为右侧的矩形的最大面积,即:
sum = max(9, 5*2) = 10
t = stack.pop() = 0
sum = max(10, 6*1) = 10
stack.push(6)
i = i + 1 = 7 (跳出循环)
返回sum=10
那么理解了代码逻辑以后,就不难写出代码:
import java.util.Stack;
public class Solution
{
// The main function to find the maximum rectangular area under given
// histogram with n bars
static int getMaxArea(int heights[])
{
Stack<Integer> stack = new Stack<>();
int[] numbers = new int[heights.length + 1];
for (int i = 0; i < heights.length; i++) {
numbers[i] = heights[i];
}
numbers[heights.length] = 0;
int sum = 0, i = 0;
while (i < numbers.length) {
if (stack.isEmpty() || numbers[i] > numbers[stack.peek()]) {
stack.add(i);
i++;
} else {
int t = stack.peek();
stack.pop();
sum = Math.max(sum, numbers[t] * (stack.isEmpty() ? i : i - stack.peek() - 1));
}
}
return sum;
}
// Driver program to test above function
public static void main(String[] args)
{
int hist[] = { 1,2,3,4,5,2 };
System.out.println("Maximum area is " + getMaxArea(hist));
}
}