双指针—接雨水
接雨水的本质:
一个位置能存多少水,取决于它左右两边最高柱子里较矮的那一个。
右边较高的柱子保证了水不会从右边流走,因此能接多少水就是左边较矮的那个柱子的事
接下来我们在通过比较左边柱子的最大高度,来计算当前位置能存储多少水
水量=左边柱子的最大高度-当前柱子高度
双指针解法就是:
用两个指针从左右两端往中间走,一边走一边算水,不用额外数组,空间O(1)。
完整步骤:
我们有 4 个变量:
left:左指针,从0开始往右走
right:右指针,从最后一位开始往左走
left_max:左边走过的最高柱子
right_max:右边走过的最高柱子
res:总雨水量
步骤流程:
比较 height[left] 和 height[right]
小的那一边,决定当前能接多少水。
因为:小的那边的 “边界” 已经确定了,水不会溢出。
通过比较小的那边的最大柱子高度(比如:比较height[left]和left_max),计算好小的那边能接多少水(如果比较结果:height[left]<left_max ——> 那么可以计算接水量 :res += left_max-height[left], 如果比较结果:height[left]>=left_max ——> 那么无法接水,更新最大值:left_max = height[left] ),最后移动小的那边的指针(left++)
重复直到两指针相遇(while循环)
核心代码实现如下:
int trap(vector
if (height.empty()) return 0;
// 四个关键变量
int left = 0; // 左指针
int right = height.size() - 1; // 右指针
int left_max = 0, right_max = 0; // 左右最高
int res = 0; // 总水量
while (left < right) { // 指针没相遇就继续
// ============== 左边更矮 ==============
if (height[left] < height[right]) {
if (height[left] >= left_max) {
// 当前柱子比左边最高还高 → 不能存水,更新最高
left_max = height[left];
} else {
// 能存水!水量 = 左边最高 - 当前高度
res += left_max - height[left];
}
left++; // 左边矮,移动左指针
// ============== 右边更矮 ==============
} else {
if (height[right] >= right_max) {
// 当前柱子比右边最高还高 → 不能存水,更新最高
right_max = height[right];
} else {
// 能存水!水量 = 右边最高 - 当前高度
res += right_max - height[right];
}
right--; // 右边矮,移动右指针
}
}
return res;
}
浙公网安备 33010602011771号