【算法】[困難]-直方圖的水量-動態規劃

17.21. 直方圖的水量

難度:[困難]python

給定一個直方圖(也稱柱狀圖),假設有人從上面源源不斷地倒水,最後直方圖能存多少水量?直方圖的寬度爲 1。

圖片.png

上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的直方圖,在這種狀況下,能夠接 6 個單位的水(藍色部分表示水)。 感謝 Marcos 貢獻此圖。數組

示例:

輸入: [0,1,0,2,1,0,1,3,2,1,2,1]
輸出: 6

【思路】動態規劃

1.記錄height中的每一個元素,從左向右掃描並記錄右邊的最大高度;<br/>
2.記錄height中的每一個元素,從右向左掃描並記錄右邊的最大高度;<br/>
3.將左右位置元素對比取最小的元素,減去數組當前元素的高度。<br/>spa

從左向右掃描並記錄右邊的最大高度

從右向左掃描並記錄右邊的最大高度

取高度最小值

Javascript

var trap = function (height) {
    let len = height.length
    if (len === 0) return 0
    //記錄左邊每一個矩形最大高度
    let left = Array(len).fill(0)
    left[0] = height[0]
    for (let i = 1; i < len; ++i) {
        left[i] = Math.max(left[i - 1], height[i])
    }
    //記錄右邊每一個矩形最大高度
    let right = Array(len).fill(0)
    right[len - 1] = height[len - 1]
    for (let i = len - 2; i >= 0; --i) {
        right[i] = Math.max(right[i + 1], height[i])
    }
    //記錄結果
    let ret = 0
    for (let i = 0; i < len; ++i) {
        //左右對比取最小邊界,減去當前矩形高度
        ret += Math.min(left[i], right[i]) - height[i]
    }
    return ret
};

go

func trap(height []int) int {
    n := len(height)
    if n == 0 {
        return 0
    }
    //記錄左邊每一個元素最大高度
    leftMax := make([]int, n)
    leftMax[0] = height[0]
    for i := 1; i < n; i++ {
        leftMax[i] = max(leftMax[i-1], height[i])
    }
    //記錄左邊每一個元素最大高度
    rightMax := make([]int, n)
    rightMax[n-1] = height[n-1]
    for i := n - 2; i >= 0; i-- {
        rightMax[i] = max(rightMax[i+1], height[i])
    }
    fmt.Println(leftMax, rightMax)
    ret := 0
    for j := 0; j < n; j++ {
        ret += (min(leftMax[j], rightMax[j]) - height[j])
    }
    return ret
}

//因爲Go語言裏面沒有max(),min()須要本身實現一個
func max(a, b int) int {
    if a-b > 0 {
        return a
    }
    return b
}
func min(a, b int) int {
    if a-b > 0 {
        return b
    }
    return a
}

Typescript

function trap(height) {
    var len = height.length;
    if (len === 0)
        return 0;
    //記錄左邊每一個矩形最大高度
    var left = Array(len);
    left[0] = height[0];
    for (var i = 1; i < len; ++i) {
        left[i] = Math.max(left[i - 1], height[i]);
    }
    //記錄右邊每一個矩形最大高度
    var right = Array(len);
    right[len - 1] = height[len - 1];
    for (var i = len - 2; i >= 0; --i) {
        right[i] = Math.max(right[i + 1], height[i]);
    }
    //記錄結果
    var ret = 0;
    for (var i = 0; i < len; ++i) {
        //左右對比取最小邊界,減去當前矩形高度
        ret += Math.min(left[i], right[i]) - height[i];
    }
    return ret;
}

python

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        if not height:
            return 0
        # 數組長度
        n = len(height)

        # 記錄左邊每一個矩形最大高度
        left = [0]*n
        left[0] = height[0]
        for i in range(1,n):
            left[i] = max(left[i - 1], height[i])

        # 記錄右邊每一個矩形最大高度
        right = [0]*n
        right[n - 1] = height[n - 1]
        for i in range(n-2,-1,-1):
            right[i] = max(right[i + 1], height[i])
        # 記錄結果
        ret = sum(min(left[i], right[i]) - height[i] for i in range(n)) 
        return ret

繼續加油!哦裏給code

相關文章
相關標籤/搜索