接雨水——算法

105 阅读1分钟

image.png

代码1.0-按列求:

  1. 每次找当前列左边的最大值,以及右边的最大值,其中,左右相对小的那个值减去当前列的值,就是当前列可以存放雨水的量
  2. 当然也不能直接减,因为为负值的时候,表示的应该是无法存放雨水,也就是存放雨水的量为0
  3. 所以减之前判断一下
func trap(he []int) int {
    ans := 0
    for i := 1; i < len(he)-1; i++ {
        l := 0
        for j := i-1; j >= 0; j-- {
            if l < he[j] {
                l = he[j]
            }
        }
        r := 0
        for j := i+1; j < len(he); j++ {
            if r < he[j]{
                r = he[j]
            }
        }
        a := min(l, r)
        if he[i] < a {
            ans = ans + a - he[i]
        }
    }
    return ans
}
func min(i,j int) int {
    if i < j {
        return i
    }
    return j
}

代码1.1按列求:

  1. 代码1.0中我们每次都for循环遍历找左和右的最大值,其实完全可以避免每次遍历
  2. 其中 L 我们可以保存最大值后,每次与新到的值做比较从而维护 L 。
  3. R 我们也可以用一个单调递减的队列维护其最大值,其中队列中存放下标,只要队首的下标还没有失效就把队首对应的he值赋值给R 就可以了,失效就弹出
func trap(he []int) int {
    ans := 0
    l := he[0]

    rr := make([]int, 0)
    push := func(i int) {
        for len(rr) > 0 && he[i] >= he[rr[len(rr)-1]] {
            rr = rr[:len(rr)-1]
        }
        rr = append(rr, i)
    }
    for i := 2; i < len(he); i++ {
        push(i)
    }

    for i := 1; i < len(he)-1; i++ {
        if l < he[i-1] {
            l = he[i-1]
        }
        if rr[0] <= i {
            rr = rr[1:]
        }
        r := he[rr[0]]
        a := min(l, r)
        if he[i] < a {
            ans = ans + a - he[i]
        }
    }
    return ans
}
func min(i,j int) int {
    if i < j {
        return i
    }
    return j
}

代码2-按行求:

图片来源,方法来源,原作者:leetcode.cn/problems/tr…

image.png

func trap(he []int) int {
    ans := 0
    max := getMax(he)   //找到最大高度,以便遍历
    for i := 1; i <= max; i++ {
        var a bool
        temp := 0   //标记是否开始更新temp,即temp已经遇到过一个大于当前i高度的值he[j]
        for j := 0; j < len(he); j++ {
            if a && he[j] < i {
                temp++
            }
            if he[j] >= i {
                ans += temp
                temp = 0
                a = true
            }
        }
    }
    return ans
}
func getMax (he []int) int {
    max := 0
    for i := 0; i < len(he); i++ {
        if max < he[i] {
            max = he[i]
        }
    }
    return max
}