收集雨水

pardon110發表於2020-10-14

題面

給出n個數字,表示一個高程圖,高程圖中每一條的寬度為1,計算下雨之後這個地形可以儲存多少水

給出[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個單位的雨水(藍色部分)被儲存。
輸入

[0,1,0,2,1,0,1,3,2,1,2,1]

輸出

6

分析

  • 關鍵 構建V型雨水收集器區間 即左右邊界及坑底
  • 確保入棧索引對應的高程資料比棧頂小,即為單調遞減棧
  • 反之出棧,前一棧頂視為坑,出棧後的棧頂視為左邊界,當前索引位為右邊界
  • 計算雨水量,長為當前索引位與當前棧頂位之差,高為兩邊界之最小峰值與前坑高程之差

上碼

func trap( A []int ) int {
    var rs int
    for i,st :=0,[]int{};i<len(A);{
        if len(st)==0 || A[i]<= A[st[len(st)-1]]{
            st = append(st,i)
            i++
        }else{
            // 將出棧位視為坑
            prev := st[len(st)-1]
            st = st[:len(st)-1]
            if len(st)>0 {
                rs += (i - st[len(st)-1] -1)*( minH(A[i], A[st[len(st)-1]]) - A[prev])
            }
        }
    }
    return rs
}
func minH(a,b int)int {
    if a < b {
        return a
    }
    return b
}

小結

  • V型序列資料,大–小–大, 出棧實現頂與底部轉化
  • 入棧單調遞減,否則二選一,出入棧時機,雨水可收集可計算條件
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章