Trapping Rain Water (双指针

给定 n 个非负整数表示每个宽度为 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 个单位的雨水。

代码如下:

class Solution {
public:
    int trap(vector<int>& height) {   //每次移动较小的柱子,计算可以接水的量
    	int left=0,right=height.size()-1;
    	int leftmax=0,rightmax=0,result=0;
    	while(left<right){  //逻辑就是,每次计算小的柱子的接水量,和尚接水逻辑
    		if(height[left]<height[right]){
    			leftmax=max(leftmax,height[left]);
    			result+=leftmax-height[left];   //宽度为1,高度相差多少体积就为多少
    			left++;
    			}
    		else{
    			rightmax=max(rightmax,height[right]);
    			result+=rightmax-height[right];
    			right--;
    			    		}
    		}
    	}
    	return result;
    }
};

过程描述

输入数据

以给出的 height = [0,1,0,2,1,0,1,3,2,1,2,1] 为例,解释如何一步步计算接到的雨水量。

初始化

使用双指针法,从数组两端开始:

  • left = 0 指向左端(位置 0)
  • right = 11 指向右端(位置 11)
  • leftMax = 0:左边遇到的最大高度
  • rightMax = 0:右边遇到的最大高度
  • result = 0:存储最终接到的雨水量

步骤 1

  • 当前 height[left] = 0height[right] = 1
  • 因为 height[left] < height[right],我们考虑 left
    • 更新 leftMaxleftMax = max(leftMax, height[left]) = max(0, 0) = 0
    • 雨水量为 leftMax - height[left] = 0 - 0 = 0,没有水可以接
    • 左指针向右移动:left = 1

步骤 2

  • 当前 height[left] = 1height[right] = 1
  • 因为 height[left] == height[right],我们考虑 right
    • 更新 rightMaxrightMax = max(rightMax, height[right]) = max(0, 1) = 1
    • 雨水量为 rightMax - height[right] = 1 - 1 = 0,没有水可以接
    • 右指针向左移动:right = 10

步骤 3

  • 当前 height[left] = 1height[right] = 2
  • 因为 height[left] < height[right],我们考虑 left
    • 更新 leftMaxleftMax = max(leftMax, height[left]) = max(0, 1) = 1
    • 雨水量为 leftMax - height[left] = 1 - 1 = 0,没有水可以接
    • 左指针向右移动:left = 2

步骤 4

  • 当前 height[left] = 0height[right] = 2
  • 因为 height[left] < height[right],我们考虑 left
    • 更新 leftMaxleftMax = max(leftMax, height[left]) = max(1, 0) = 1
    • 雨水量为 leftMax - height[left] = 1 - 0 = 1,可以接 1 个单位的雨水
    • 更新 result = result + 1 = 0 + 1 = 1
    • 左指针向右移动:left = 3

步骤 5

  • 当前 height[left] = 2height[right] = 2
  • 因为 height[left] == height[right],我们考虑 right
    • 更新 rightMaxrightMax = max(rightMax, height[right]) = max(1, 2) = 2
    • 雨水量为 rightMax - height[right] = 2 - 2 = 0,没有水可以接
    • 右指针向左移动:right = 9

步骤 6

  • 当前 height[left] = 2height[right] = 1
  • 因为 height[left] > height[right],我们考虑 right
    • 更新 rightMaxrightMax = max(rightMax, height[right]) = max(2, 1) = 2
    • 雨水量为 rightMax - height[right] = 2 - 1 = 1,可以接 1 个单位的雨水
    • 更新 result = result + 1 = 1 + 1 = 2
    • 右指针向左移动:right = 8

步骤 7

  • 当前 height[left] = 2height[right] = 2
  • 因为 height[left] == height[right],我们考虑 right
    • 更新 rightMaxrightMax = max(rightMax, height[right]) = max(2, 2) = 2
    • 雨水量为 rightMax - height[right] = 2 - 2 = 0,没有水可以接
    • 右指针向左移动:right = 7

步骤 8

  • 当前 height[left] = 2height[right] = 3
  • 因为 height[left] < height[right],我们考虑 left
    • 更新 leftMaxleftMax = max(leftMax, height[left]) = max(1, 2) = 2
    • 雨水量为 leftMax - height[left] = 2 - 2 = 0,没有水可以接
    • 左指针向右移动:left = 4

步骤 9

  • 当前 height[left] = 1height[right] = 3
  • 因为 height[left] < height[right],我们考虑 left
    • 更新 leftMaxleftMax = max(leftMax, height[left]) = max(2, 1) = 2
    • 雨水量为 leftMax - height[left] = 2 - 1 = 1,可以接 1 个单位的雨水
    • 更新 result = result + 1 = 2 + 1 = 3
    • 左指针向右移动:left = 5

步骤 10

  • 当前 height[left] = 0height[right] = 3
  • 因为 height[left] < height[right],我们考虑 left
    • 更新 leftMaxleftMax = max(leftMax, height[left]) = max(2, 0) = 2
    • 雨水量为 leftMax - height[left] = 2 - 0 = 2,可以接 2 个单位的雨水
    • 更新 result = result + 2 = 3 + 2 = 5
    • 左指针向右移动:left = 6

步骤 11

  • 当前 height[left] = 1height[right] = 3
  • 因为 height[left] < height[right],我们考虑 left
    • 更新 leftMaxleftMax = max(leftMax, height[left]) = max(2, 1) = 2
    • 雨水量为 leftMax - height[left] = 2 - 1 = 1,可以接 1 个单位的雨水
    • 更新 result = result + 1 = 5 + 1 = 6
    • 左指针向右移动:left = 7

最终结果

此时 left == right,循环结束,最终 result = 6,表示可以接到的雨水总量为 6。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值