Leetcode 84. 柱狀圖中最大的矩形 Largest Rectangle in Histogram

https://leetcode-cn.com/probl...python

會超時的方法:

雙重循環

最簡單的思路,時間複雜度 O(n^2) 會超時(最後附超時代碼)算法

分治算法

先找到當前數組中最小元素。數組

那麼答案將在一下三種狀況中:app

  1. 包含最小元素,那麼高度是最小元素高度,長度是整個區間
  2. 不包含最小元素,且在最下元素左邊 (遞歸左半區間)
  3. 不包含最小元素,且在最下元素有邊 (遞歸右半區間)

這個方法的平均時間複雜度是 O(nlogn)code

可是最壞狀況時間複雜度還是 O(n^2) 也會超時(最後附超時代碼)遞歸

正確解法

從前向後遍歷,過程當中維護一個遞增的棧。leetcode

若是下一個大於棧頂元素,就直接入棧。get

若是小於,就把棧裏大的元素都彈出來,而且計算高度是彈出的元素高度,寬度是當前元素到棧頂元素之間。博客

爲何能夠以彈出元素高度爲高度,當前位置和棧頂元素位置間的距離爲寬度呢?由於棧是遞增的,比彈出元素高度低的元素必定都在棧裏,棧頂必定是離這個元素最近的一個(高度小於該元素的元素)換句話就是它們之間的元素高度都大於該元素。io

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        hs = [0] + heights + [0]
        s = []
        ans = 0
        for i, h in enumerate(hs):
            while s and hs[s[-1]] > h:
                j = s.pop()
                ans = max(ans, hs[j] * (i-s[-1]-1))
            s.append(i)
        return ans

超時代碼

超時代碼一 雙重循環

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        maxa = 0
        for i in range(len(heights)):
            minh = heights[i]
            for j in range(i, len(heights)):
                minh = min(minh, heights[j])
                maxa = max(maxa, minh * (j-i+1))
        return maxa

超時代碼二 分治

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        def solve(l, r, d):
            if l >= r: return 0
            if l == r-1: return heights[l]
            min_i = l
            min_h = heights[l]
            for i, h in enumerate(heights[1+l:r]):
                if h < min_h:
                    min_h = h
                    min_i = i+l+1
            return max(min_h * (r - l), solve(l, min_i, d+1), solve(min_i+1, r, d+1))
        return solve(0, len(heights), 0)

參考

歡迎來個人博客: https://codeplot.top/
個人博客刷題分類:https://codeplot.top/categories/%E5%88%B7%E9%A2%98/

相關文章
相關標籤/搜索