ethan

ethan

新知,热爱生活,码农,读书
twitter
email
github

LCR 42. 接雨水

給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。

image.png
輸入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
輸出:6
解釋:上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。
示例 2:

輸入:height = [4,2,0,3,2,5]
輸出:9

提示:
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105

解法 1:單調棧
解題思路:
對於低的柱子入棧,當出現比棧頂高的柱子,則認為可以進行一波計算。計算雨水的時候需要注意的是雨水區域的右邊 r 指的自然是當前索引 i 底部是棧頂 ,因為遇到了更高的右邊,所以它即將出棧,使用cur 來記錄它,並讓它出棧左邊l 就是新的棧頂雨水的區域全部確定了,水坑的高度就是左右兩邊更低的一邊減去底部,寬度是在左右中間使用乘法即可計算面積。

func trap(height []int) int {
	stack := make([]int, 0)
	ret := 0
	for i := 0; i < len(height); i++ {
		for len(stack) != 0 && height[stack[len(stack)-1]] < height[i] {
			cur := stack[len(stack)-1]
			stack = stack[:len(stack)-1]
			if len(stack) == 0 {
				break
			}
			h := height[i]
			if height[stack[len(stack)-1]] < h {
				h = height[stack[len(stack)-1]]
			}
			w := i - stack[len(stack)-1] - 1
			ret += w * (h - height[cur])
		}
		stack = append(stack, i)
	}
	return ret
}

解法 2: 當前柱子能否蓄水,取決於左右的最大值和當前柱子的差值

func max_num(arr []int) int {
    max := 0
    for i:= 0; i< len(arr);i++ {
        x := arr[i]
        if x > max {
            max = x
        }
    }
    return max
}
func trap(height []int) int {
    left_max_arr := make([]int, 0)
    right_max_arr := make([]int, 0)
    ret := 0
	for i:=0;i<len(height);i++ {
        left_max_arr  = append(left_max_arr, max_num(height[:i]))
        right_max_arr = append(right_max_arr, max_num(height[i:]))
    }
    for i:=0;i<len(height);i++ {
        if left_max_arr[i] < right_max_arr[i] {
            if left_max_arr[i]> height[i] {
                ret += left_max_arr[i] - height[i]
            }
        }else{
            if right_max_arr[i] > height[i] {
                ret += right_max_arr[i] - height[i]
            }
        }
    }
    return ret
}

解法三:雙指針解法
從上面的思路,很容易引出雙指針解法,將算法的空間複雜度從 o (n) 降到 o (1)

func trap(height []int) int {
	left := 0
    right := len(height)-1
    left_max := 0
    right_max := 0
    ret := 0
    for left < right {
        water_level := left_max
        if left_max > right_max {
            water_level = right_max
        }
        if height[left] <= water_level {
            ret += water_level-height[left]
            left += 1
            continue
        }
        if height[right] <= water_level {
            ret += water_level-height[right]
            right -= 1
            continue
        }
        if left_max < height[left] {
            left_max = height[left]
        }
        if right_max < height[right] {
            right_max = height[right]
        }
    }
    return ret
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。