【动态规划&&双指针】——接雨水

519 阅读1分钟

「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

题目

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

image.png

输入: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 个单位的雨水(蓝色部分表示雨水)。

题目来源:力扣(LeetCode)

代码

动态规划

1.使用两个数组leftMax和rightMax维护以i位置上左边最大值和右边最大值(包括了i位置)

2.leftMax和rightMax中较小部分和i位置所能形成的差就是i位置能够存放的水滴值

class Solution {
    public int trap(int[] height) {
        if (height == null || height.length == 0) return 0;
        int n = height.length;
        int[] leftMax = new int[n];//左边部分
        int[] rightMax = new int[n];//右边部分
        leftMax[0] = height[0]; //初始化
        rightMax[n - 1] = height[n - 1];
        for (int i = 1; i < n; i++) {
            leftMax[i] = Math.max(leftMax[i - 1], height[i]);//更新最大值
        }
        for (int i = n - 2; i >= 0; i--) {
            rightMax[i] = Math.max(rightMax[i + 1], height[i]);//更新最大值
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans += Math.min(leftMax[i], rightMax[i]) - height[i];//两边最小的是能够装水的高度
        }
        return ans;
    }
}

双指针

前面使用动态规划的方法需使用两个额外的数组空间,空间复杂度为O(N),这边使用两个指针leftMax和rightMax来替代这两个数组,将空间复杂度优化为O(1)

class Solution {
    public int trap(int[] height) {
        if (height == null || height.length == 0) return 0;
        int n = height.length;
        int left = 0; //左指针
        int right = n - 1; //右指针
        int leftMax = height[left]; //维护左边最大值
        int rightMax = height[right]; //维护右边最大值
        int ans = 0;
        while (left < right) {
            leftMax = Math.max(height[left], leftMax);//更新左边最大值
            rightMax = Math.max(height[right], rightMax);   //更新右边最大值
            if (height[left] < height[right]) { //由于经历了前两步的更新操作,这个实际上 <=> leftMax< rightMax 
                ans += leftMax - height[left];  
                left++; //此时计算完了left位置上能够装下的水滴的数量 left++ 移动
            } else {
                ans += rightMax - height[right];
                right--;    //此时计算完了right位置上能够装下的水滴的数量 right++ 移动
            }
        }
        return ans;
    }
}