[LeetCode-Python版]相向双指针——42. 接雨水

题目

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:
[LeetCode-Python版]相向双指针——42. 接雨水_第1张图片

输入: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 * 10^4
  • 0 <= height[i] <= 10^5

题目链接

思路1

  1. 用两个数组,一个记录前缀和(左侧的最大高度),一个记录后缀和(右侧的最大高度)
    • 前缀和数组 front:这个数组用来存储从数组的开始到当前位置 i 的最大高度。这意味着,对于数组中的任意位置 i,front[i] 表示从数组的开始到 i 的所有位置上,最高的柱子的高度。
    • 后缀和数组 back:这个数组用来存储从数组的结束到当前位置 i 的最大高度。这意味着,对于数组中的任意位置 i,back[i] 表示从数组的结束到 i 的所有位置上,最高的柱子的高度。
  2. 通过这些预先计算的结果来快速确定每个位置能够接住的雨水量。
    • 能接水的量 = min(前缀,后缀)-height

时空复杂度1

时间复杂度:O(n),其中 n 为 height 的长度。
空间复杂度:O(n)。

参考代码1

class Solution:
    def trap(self, height: List[int]) -> int:
        # 前缀和数组,其中第0个是原数组的第0个
        front = [0]*len(height)
        front[0] = height[0]

        # 后缀和数组,其中第-1个是原数组的第-1个
        back = [0]*len(height)
        back[-1] = height[-1]
        res = 0

        for i in range(1,len(height)):
            front[i] = max(front[i-1],height[i])
        for j in range(len(height)-2,-1,-1):
            back[j] = max(back[j+1],height[j])

        for h,f,b in zip(height,front,back):
            res+=min(f,b)-h
        return res
          

思路2

用两个变量记录前缀最大值和后缀最大值,一边移动指针一边更新最大值

  1. 如果前缀最大值<后缀最大值:
    • 说明当前位置的左侧高度是限制水容量的短边,则木桶容量是前缀最大值-当前位置高度。算完后前缀最大值向右扩展
  2. 如果后缀最大值<前缀最大值
    • 说明当前位置的右侧高度是限制水容量的短边,则木桶容量是后缀最大值-当前位置高度。算完后后缀最大值向左扩展

时空复杂度2

时间复杂度:O(n),其中 n 为 height 的长度。
空间复杂度:O(1)。

参考代码2-1

如果在外面给 lmax 和 rmax 赋值,那么循环里就在后面更新lmax 和rmax

class Solution:
    def trap(self, height: List[int]) -> int:
        lmax = height[0]
        rmax = height[-1]
        res = 0
        l = 0
        r =len(height)-1

        while l<r:
            if lmax < rmax:
                res+= lmax - height[l]
                l+=1
            else:
                res+=rmax-height[r]
                r-=1
            lmax = max(lmax,height[l])
            rmax = max(rmax,height[r])
        return res   

参考代码2-2

如果不在外面赋值,就在最开始就更新lmax 和rmax

class Solution:
    def trap(self, height: List[int]) -> int:
        lmax = 0
        rmax = 0
        res = 0
        l = 0
        r =len(height)-1

        while l<r:
            lmax = max(lmax,height[l])
            rmax = max(rmax,height[r])
            
            if lmax < rmax:
                res += lmax - height[l]

                l+=1
            else:
                res += rmax - height[r]
                r-=1
        return res

        

Q&A

  1. 为什么不能在里面if-else里面更新lmax 和rmax?
    需要确保在每次迭代中,lmax 和 rmax 都是到当前指针位置为止的最大高度,从而正确计算每个位置的积水量
    如果只在if-else里更新,则每次只更新一个指针,无法确保另一个指针是否是最大高度

你可能感兴趣的:(LeetCode-Python,leetcode,python,android)