【LeetCode】解题42:Trapping Rain Water

Problem 42: Trapping Rain Water [Hard]

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
在这里插入图片描述
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

来源:LeetCode

解题思路

每根柱子上的水面高度受其左右两边最高的那根柱子的影响,如果自己本身是最高点,则留不住水。
基本思路为从左往右和从右往左两次遍历,找出每一个柱子左边和右边的最高高度,取两数中较小值即为能困住的水面高度。

具体过程:

  • 首先从左往右遍历数组,在trapHeight[N]中记录下每根柱子左边的最高点(max(trapHeight(i-1), height[i]))。如果左边的柱子都不如自身高,则记录自身的高度。
    如例图中输入,则trapHeiht取值如下:
    左边最高点
  • 从右往左遍历数组,首先计算出每根柱子右边的最高点(max(trapHeight[i+1], height[i])),然后与左边最高点(trapHeight[i])作比较,选出较小的值即为当前柱子的水面高度。
    例图中trapHeight的值更改如下:
    在这里插入图片描述
  • 最后将每根柱子上的水面高度与自身高度之差累积,即为困住的雨水体积。
  • 注意:数组最左边和最右边的的柱子本身一定为自身的最高点,因为二者左边或右边没有其他柱子,一定留不住比自己高的水面。

整个算法一共遍历了两次数组,时间复杂度为O(n),空间复杂度为O(n)。

运行结果:
在这里插入图片描述

Solution (Java)

class Solution {
    public int trap(int[] height) {
        int N = height.length;
        if(N == 0) return 0;
        int[] trapHeight = new int[N]; 
        // max height on the left of each bar
        trapHeight[0] = height[0];
        for(int i = 1; i < N; i++){
            trapHeight[i] = Math.max(trapHeight[i-1], height[i]);
        }
        // water height of each bar
        trapHeight[N-1] = height[N-1];
        for(int i = N-2; i >= 0; i--){
            trapHeight[i] = Math.min(Math.max(trapHeight[i+1],height[i]),trapHeight[i]);
        }
        int water = 0;
        for(int i = 1; i < N-1; i++){
            if(trapHeight[i] > height[i]){
                water += trapHeight[i] - height[i];
            }
        }
        return water;
    }
}

修改过程

  • 第一次提交没有考虑N=0的情况。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值