【LeetCode】84.柱狀圖中最大的矩形

題目鏈接

84. 柱狀圖中最大的矩形

題目描述

解題思路

暴力法

對於每一個高度height[i],我們可以向左向右遍歷,然後算出該高度往左往右最多可以延申至何處,這樣就能算出該高度對應的面積,枚舉所有高度然後求出最大值。

時間複雜度:O(n)

空間複雜度:O(1)

超時!

單調棧

以上暴力寫法 Java 可以通過,但我們不妨想一下這裏的雙重循環是否可以優化?

我們每遍歷到當前柱體 i 時:暴力解法中我們需要再嵌套一層 while 循環來向左找到第一個比柱體 i 高度小的柱體,這個過程是 O(N) 的;
那麼我們可以 O(1)的獲取柱體 i 左邊第一個比它小的柱體嗎?答案就是單調增棧,因爲對於棧中的柱體來說,棧中下一個柱體就是左邊第一個高度小於自身的柱體。

因此做法就很簡單了,我們遍歷每個柱體,若當前的柱體高度大於等於棧頂柱體的高度,就直接將當前柱體入棧,否則若當前的柱體高度小於棧頂柱體的高度,說明當前棧頂柱體找到了右邊的第一個小於自身的柱體,那麼就可以將棧頂柱體出棧來計算以其爲高的矩形的面積了。

小trick:爲長度數組首位加上兩個0,便於計算,同時可以解決高度遞增序列現象問題。

AC代碼

暴力法

class Solution {
    public int largestRectangleArea(int[] heights) {
        int area = 0, n = heights.length;
        // 遍歷每個柱子,以當前柱子的高度作爲矩形的高 h,
        // 從當前柱子向左右遍歷,找到矩形的寬度 w。
        for (int i = 0; i < n; i++) {
            int w = 1, h = heights[i], j = i;
            while (--j >= 0 && heights[j] >= h) {
                w++;
            }
            j = i;
            while (++j < n && heights[j] >= h) {
                w++;
            }
            area = Math.max(area, w * h);
        }

        return area;
    }
}

單調棧法

class Solution {
    public int largestRectangleArea(int[] heights) {
        int ans = 0;
        int cHeights[] = new int[heights.length+2];
        cHeights[0] = 0;
        cHeights[heights.length+1] = 0;
        for(int i = 1; i < heights.length+1; i++){
            cHeights[i] = heights[i-1];
        }
        Stack<Integer> st = new Stack<>();
        for(int i = 0; i < cHeights.length; i++){
            while(!st.isEmpty() && cHeights[i] < cHeights[st.peek()]){
                int height = cHeights[st.pop()];
                ans = Math.max(ans,height * (i - st.peek() - 1));
            }
            st.push(i);
        }
        return ans;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章