【LeetCode】接雨水 [H](双指针)

42. 接雨水 - 力扣(LeetCode)

一、题目

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

示例 1:
 

【LeetCode】接雨水 [H](双指针)_第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 * 104
  • 0 <= height[i] <= 105

二、代码

class Solution {
    public int trap(int[] height) {
        // 长度小于等于2的都存不住水
        if (height == null || height.length <= 2) {
            return 0;
        }

        int n = height.length;
        // 左右指针,分别从1和n-2开始
        int l = 1;
        int r = n - 2;
        // 左部分最大高度,一开始设置为 height[0]
        int leftMax = height[0];
        // 右部分最大高度,一开始设置为 height[n - 1]
        int rightMax = height[n - 1];

        // 记录总的水量
        int sum = 0;
        // 左右指针开始向中间遍历结算水量
        while (l <= r) {
            int water;
            // 每次结算左右max比较小的那一侧的水量
            // 如果leftMax和rightMax相等,就同时结算
            // 结算的就是左右指针指向的位置
            if (leftMax <= rightMax) {
                // 以leftMax作为瓶颈,如果相减小于0,那么l位置的水量就是0
                water = leftMax - height[l];
                sum += (water > 0 ? water : 0);
                // 更新leftMax,并且左指针右移
                leftMax = Math.max(height[l++], leftMax);
            } 

            // 如果存在leftMax和rightMax相等的情况,那么左右两边就要同时结算,并且我们要保证l<=r,因为有可能出现上面的结算完之后其实已经将所有的位置都结算一遍了,然后就不能再进入这个分支了,防止同一个位置重复结算
            if (leftMax >= rightMax && l <= r) {
                // 以rightMax作为瓶颈,如果相减小于0,那么r位置的水量就是0
                water = rightMax - height[r];
                sum += (water > 0 ? water : 0);
                // 更新rightMax,并且右指针zuo移
                rightMax = Math.max(height[r--], rightMax);
            } 
        }

        return sum;
    }
}

三、解题思路 

使用双指针,并且还要用两个变量来记录左右两部分目前已知的最大高度左max和右max。整个流程详细写在代码注释中了。

你可能感兴趣的:(#,LeetCode,#,数据结构,#,算法,leetcode,数据结构,算法,双指针,贪心)