題解:給出的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));
}
}