ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

接雨水-双指针42-pythonc++

接雨水-双指针42-pythonc++

循环逻辑一步步说:

  1. 每次先更新左右两边的最高墙:看看当前柱子会不会刷新left_max/right_max
  2. 判断:如果左边最高墙 < 右边最高墙
    ✅ 说明:对于left这个位置,它能存水的上限就是left_max。
    因为右边已经有一堵更高的墙兜底了,不用担心右边不够高,水不会流走。
    能存水 =left_max - height[left],加到结果,左指针右移。
  3. 否则(right_max <= left_max)
    ✅ 说明:对于right这个位置,存水上限是right_max。
    左边有更高的墙兜底,水不会往左跑。
    能存水 =right_max - height[right],加到结果,右指针左移。
  4. 直到两个指针碰面,全部位置算完,返回总雨水。

python

classSolution(object):deftrap(self,height):""" :type height: List[int] :rtype: int """left,right=0,len(height)-1left_max=right_max=0res=0whileleft<=right:left_max=max(left_max,height[left])right_max=max(right_max,height[right])ifleft_max<right_max:res+=left_max-height[left]left+=1else:res+=right_max-height[right]right-=1returnres

c++
时间和空间复杂度均为O(N),但是思路好理解

classSolution{public:inttrap(vector<int>&height){// 遍历到i位置,就只关心该位置能接多少雨水// 通过两个数组来维护0-i的最大高度和i到n-1的最大高度// 再根据木桶效应,得知i位置能接的雨水只与这两个最大值中的较小值有关intn=height.size();vector<int>left_max(n,height[0]);vector<int>right_max(n,height[n-1]);intres=0;for(inti=1;i<n;i++){left_max[i]=max(height[i],left_max[i-1]);}for(inti=n-2;i>=0;i--){right_max[i]=max(height[i],right_max[i+1]);}for(inti=0;i<n;i++){res+=min(left_max[i],right_max[i])-height[i];}returnres;}};

时间复杂度仍为O(N),优化空间复杂度为O(1),思路稍微有些绕

classSolution{public:inttrap(vector<int>&height){// 遍历到某个位置,就只关心该位置能接多少雨水// 通过两个变量max_left和max_right,可以得知左指针left和右指针right的height[0:left]和height[right:-1]的各自最大值// 再根据木桶效应,得知某个位置能接的雨水只与这两个最大值中的较小值有关intleft=0,right=height.size()-1;intmax_left=0,max_right=0;intres=0;while(left<right){max_left=max(max_left,height[left]);max_right=max(max_right,height[right]);if(max_left<max_right){res+=max_left-height[left];left++;}else{res+=max_right-height[right];right--;}}returnres;}};
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进