leetcode題解-84.Largest Rectangle in Histogram

題解:給出的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));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章