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

示例 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

官方正解:

当前列可以承载的雨滴数= min(当前列左右两侧的最大值)-当前列的大小;

这道题目的解题思路我做个总结:
首先大家要明白一个基本公式:
当前列可以承载的雨滴数= min(当前列左右两侧的最大值)-当前列的大小;
就是当前这个列的左边最高列和右边最高列中的最小那个 与 本列的差值是否大于>0
对这个公式有疑问的,可自行验证!
那么我把每一列可以承载的雨滴数加起来就是这个数组整体可以承载的雨滴数了。

基于上面的公式我们再去理解这个双指针解题思路:
1、先讲讲左指针的情况:
左指针从左往右走,那么对于其左侧的最大值是自己所走过的列中最大值,而右侧的最大值我们不知?
但我们不必关心左指针的右侧最大值具体是多少,我们只需在左侧最大值小于右侧最大值的情况下,就可以根据上面的公式计算出当前列可以承载的雨滴数,因为左指针的左侧最大值是明确的!
而我们可以确定的是:
左指针右侧最大值一定>=右指针的右侧最大值;因为两头的值已经被两个指针走过了,是明确的值,而两个指针中间的值不明确,因此左指针这个右侧的最大值要么更大,要么就是当前已经出现在右指针遍历过的值中。
2、右指针同理:
右指针右侧的最大值是明确的,其左侧的最大值暂不知道,但可以确定的是:右指针左侧最大值一定>=左指针的左侧最大值

3、开始解题:
那么现在问题就很简单了,遍历整个数组,比较左指针左侧的最大值和右指针的右侧最大值情况就能计算完整个数组
如果:左指针左侧最大值<右指针右侧最大值<=(左指针右侧最大值一定),说明对于左指针而言,我的左边最高列小于右边最高列,而我的左边最高列我是知道具体值的,那么就计算左指针当前列可承载雨滴数,并右移左指针,右指针原地不动。
反之:(右指针左侧最大值一定)>=左指针左侧最大值>右指针右侧最大值,说明对于右指针而言,我左边的最高列>右边的最高列,那么就可依据右边最高列值进行计算,并左移右指针,左指针原地不动。
class Solution {
    public int trap(int[] height) {
        int result = 0;
        int left = 0;
        int right = height.length - 1;
        int maxLeft = 0;
        int maxRight = 0;
        while (left < right) {
            maxLeft = Math.max(maxLeft, height[left]);
            maxRight = Math.max(maxRight, height[right]);
            if (maxLeft < maxRight) {
                result += maxLeft - height[left];
                left++;
            } else {
                result += maxRight - height[right];
                right--;
            }
        }
        return result;
    }
}
posted on 2025-07-09 16:31  caoshikui  阅读(11)  评论(0)    收藏  举报