LeetCode 42:接雨水

一、题目描述

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

示例 1:

LeetCode 42:接雨水_第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

二、思路分析

本题的解法有很多,这里使用动态规划进行解答。首先,动态规划是:通过将原问题分解为相对简单的子问题的方式求解复杂问题的方法。

根据本题题意,我们需要找到存在凹槽的地方,这样才能够积攒雨水。首先创建两个数组,maxLeft [i] 代表第 i 列左边最高的墙的高度,maxRight [i] 代表第 i 列右边最高的墙的高度。(要注意下,第 i 列左(右)边最高的墙,是不包括自身的)

对于 maxLeft 我们可以这样求:

maxLeft[i] = Math.max(maxLeft[i - 1], height[i - 1]); 它前边的墙的左边的最高高度和它前边的墙的高度选一个较大的,就是当前列左边最高的墙了。

对于 maxRight 我们可以这样求:

maxRight[i] = Math.max(maxRight[i + 1], height[i + 1]); 它后边的墙的右边的最高高度和它后边的墙的高度选一个较大的,就是当前列右边最高的墙了。

三、代码参考

1、Java

class Solution {
    public int trap(int[] height) {
        // 用来计算最终结果,初始值为 0
        int sum = 0;
        // 创建数组 maxLeft,用来表示第 i 列左边最高的墙
        int[] maxLeft = new int[height.length];
        // 创建数组 maxRight,用来表示第 i 列右边最高的墙
        int[] maxRight = new int[height.length];
        // 循环遍历,获得数组中每一列左边最高的墙
        for(int i = 1; i < height.length; i++){
            // 获得第 i 列左边最高的墙
            maxLeft[i] = Math.max(maxLeft[i - 1], height[i - 1]);
        }
        // 循环遍历,获得数组中每一列右边最高的墙
        for(int i = height.length - 2; i >= 0; i--){
            // 获取第 i 列右边最高的墙
            maxRight[i] = Math.max(maxRight[i + 1], height[i + 1]);
        }
        // 通过 maxLeft 和 maxRight 两个数组来获取第 i 列左右两边的墙谁最矮,因为凹槽的积水面积的高度取决于矮的一边
        for(int i = 1; i < height.length; i++){
            // 获取第 i 列左右两边墙高度最小的值
            int min = Math.min(maxLeft[i], maxRight[i]);
            // 如果有凹槽,即当前列的高度小于列左右两边最小的高度
            if(min > height[i]){
                // 计算当前列的积水面积,并汇总
                sum = sum + (min - height[i]);
            }
        }
        // 返回结果
        return sum;
    }
}

你可能感兴趣的:(数据结构与算法,算法,leetcode,python,java,数据结构,动态规划)