双指针解决leetcode 42. 接雨水 与 11. 盛最多水的容器

第一次在leetcode A一道high难度的题,纪念一下

11. 盛最多水的容器 <-点击跳转

这道题思路很简单,设想一下,盛多少水是由最低的墙决定的,我们设两个指针,左指针l从头开始,右指针r从尾部开始,那么当前的容量v = min(height[l] ,height[r]) * len(l , r)。
那么下次用来和这次比较大小的容积是怎么找的呢?
很简单,设想一下,左右向内移动,那么len一定会减少,那么我们一定想让min尽可能大,所以只要让l和r中高度最小的变化就可以了。
浅证一下:如果当前height[l] < height[r] ,那么 v = min(height[l] ,height[r]) * len(l , r) = height[l] * len(l , r) , 又已知变化后的lenNew < 变化前的len ,那么向左移动右指针设此时 r 变为 rNew
如果 height[rNew] >= height[r] 那么 min = height[l] , vNew = height[l] * lenNew < v
如果 height[rNew] < height[r] 那么 min <= height[1] , vNew <= height[l] * lenNew < v
由以上可知,如果移动高度小的指针得到的容积必然比原来的小,所以上面要求动高度最小的

所以代码轻轻松松出来了:

func maxArea(height []int) int {
    len := len(height)
    l := 0
    r := len - 1
    ans := 0 
    for {
        ans = max(ans , sumAns(height , l , r))
        if height[l] < height[r] && l != r {
            l++
        }else{
            r--
        }
        if l == r {
            return ans
        }
    }

    return ans
}

func sumAns(h []int,l int,r int) int{
        return min(h[l] , h[r]) * (r - l)
    }

func max(a int,b int) int {
    if a > b {
        return a
    } else {
        return b
    }
}

func min(a int,b int) int {
    if a < b{
        return a
    }else {
        return b
    }
}

这时候,我看到了另一个题,
< 42. 接雨水

看到题目的描述,也是容积的问题,我就想能不能通过双指针解决。
一开始,我的思路是通过快慢指针,找到右边快指针所在墙壁小于慢指针所在墙壁的地方,然后差值加入答案,后来发现,全是error,ToT
仔细一想,其实当前位置所能积水的量,实际上由当前位置左边最大墙和右边最大墙中最小的墙决定的,是不是很拗口qwq,上图

解决了思路,那么我们就该考虑代码了
还是快慢指针,第一次可以判断,左边最大的墙leftmax 就是慢指针当前的墙高,右边最大的rightmax 就是快指针的墙高,那么第一次不管是快指针所在的容积和慢指针所在的容积都是0,
那么下一个位置该判断谁的容积呢?或者说是快指针先动还是慢指针先动呢?
其实这里和上面那道题一样,小的先动,为什么呢?
如果当前左边墙已经比右边墙高了,由上面可知,能不能积水看的是最低的墙,那么左边的位置一定是不能装水的,需要右边位置向里面挪,找到下一个需要积水的位置。
那么找到了需要积水的位置如何计算?向那个方向移动的指针,结果就等于这个方向上的最大墙-当前的墙高,为什么呢?
因为我们每次都是小的先动,例如右边小,右边向里动,那么左边的一定是高的,那么就把右边小的里面最大的找出来减掉当前的墙高就是结果

那么我们上代码:

func trap(height []int) int {
    l := 0
    r := len(height) - 1
    maxl := height[l]
    maxr := height[r]
    ans := 0
    if len(height) <= 1 {
        return 0
    }
    for {
        maxl = max(maxl,height[l])
        maxr = max(maxr,height[r])
        if maxl >= height[r] {
          ans += maxr - height[r]
          r--
        }else if maxr >= height[l] {
          ans += maxl - height[l]
          l++
        }
        if r == l {
            break
        }
    }
    return ans
}

func max(a int,b int) int{
    if a > b {
        return a
    }else {
        return b
    }
}
posted @ 2022-04-16 18:36  JiaoMaster  阅读(64)  评论(0编辑  收藏  举报