LeetCode:42. 接雨水

本文介绍了如何使用动态规划算法解决给定高度图中计算雨水接收到的总量问题,通过左右指针移动和区间水滴数计算实现。代码展示了如何在Java中实现这一过程。
摘要由CSDN通过智能技术生成

1)题目

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

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

2)思路

初始指针:左指针放第一个位置,右指针放左指针后面一个位置
当左指针大于右指针时,右指针往后移,直到移动到右指针大于左指针为止;
当左指针小于右指针时,计算该区间内的水滴数,之后左指针移动到右指针的位置,右指针移动到左指针之后。
由此左低右高的柱子区间水滴数统计完成
		  0  1  2  3  4  5  6  7  8  9  10 11
height = [0, 1, 0, 2, 1, 0, 1 ,3, 2, 1, 2, 1]
		  l0 r1             						l<r  l=r r=r+1
		     l1 r2									l>r  r++
		  	 l1	   r3								l<r  (r-l-1)*l1-(r2) l=r r=r+1
				   l3 r4 r5 r6  					l>r  r++ ... 
				   l3          r7					l<r  (r-l-1)*l3-(r4+r5+r6) l=r r=r+1
				   			   l7 r8 r9 r10 r11		l>r  r++ ... r=len 结束
(r-l-1)*l1-(r2) = (3-1-1)*1-0 = 1
(r-l-1)*l3-(r4+r5+r6) = (7-3-1)*2-(1+0+1) = 4

反过来统计左高右低的柱子区间水滴数,注意l<=r
height = [0, 1, 0, 2, 1, 0, 1 ,3, 2, 1, 2,  1]
										l10 r11		l>r r=l l=r-1
									 l9 r10			l<r l-- 
								  l8    r10			l=r l-- 
							   l7       r10			l>r (r-l-1)*r10-(r9+r8) r=l l=r-1
		  l0 l1 l2 l3 l4 l5 l6 r7					l<r l-- ... l=0 结束
(r-l-1)*r10-(r9+r8) = (10-7)*2-(1+2) = 1
水滴数 = 1+4+1 =6

3)代码

public static int trap(int[] height) {
    if (height.length < 3) return 0;
    int left = 0, right = 1;
    int num = 0;
    while (left < height.length - 1 && right < height.length) {
        if (height[left] > height[right]) {
            right++;
        } else {
            num += getNum(height, left, right, num);
            left = right;
            right = left + 1;
        }
    }
    left = height.length-2;
    right = height.length-1;
    while (right > 0 && left >= 0) {
        if (height[left] <= height[right]) {
            left--;
        } else {
            num += getNum(height, left, right, num);
            right = left;
            left = right - 1;
        }
    }

    return num;
}

/**
 * 获取两个柱子之间接水的数量
 * @return (r-l-1)*min(l,r)-中间值之和
 */
private static int getNum(int[] height, int left, int right, int num) {
    int middleLen = right - left - 1;
    int middleValueNum = 0;
    for (int i = 1; i <= middleLen; i++) {
        middleValueNum += height[left + i];
    }
    int min = height[left] < height[right] ? height[left] : height[right];
    return middleLen * min - middleValueNum;
}

4)结果

在这里插入图片描述

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值