LeetCode_双指针_困难_42.接雨水

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
0 <= n <= 3 * 104
0 <= height[i] <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water

2.思路

(1)暴力穷举法
暴力穷举法的主要思想在于求出每个位置 i 能够接的雨水量,然后将其全部相加即可。而位置 i 能达到的水柱高度和其左边的最高柱子、右边的最高柱子有关,这里分别称这两个柱子高度为 leftMax 和 rightMax,那么位置 i 最大的水柱高度就是 min(leftMax, rightMax),该位置可以接的雨水量为 min(max(height[0...i]), max(height[i...end])) - height[i]

(2)双指针
① 定义雨水量 res 以及分别指向数组首和数组尾的指针 left 和 right, 初始值分别为 0、0、height.length - 1。

② 维护所有位置左右两侧高度最高的柱子 leftMax 和 rightMax,对于某侧的柱子,若存在高度更高的柱子则可以舍弃,因此哪侧柱子高度底,就更新哪侧(它们的初始值均为 0);

③ 当两指针没有相遇时,使用 height[i] 和 height[j] 分别来更新 leftMax 和 rightMax 的值;

  • 若 leftMax < rightMax,计算下标 left 处能够接到的雨水量 leftMax - height[left],并累加给 res,并且 left 向后移动一位;
  • 若 leftMax ≥ rightMax,计算下标 right 处能够接到的雨水量 rightMax - height[right],并累加给 res,并且 right 向前移动一位;

④ 两指针相遇后,结束 while 循环,直接返回 res 即可。

相关题目:
LeetCode_双指针_中等_11.盛最多水的容器

3.代码实现(Java)

//思路1————暴力穷举法
class Solution {
	public static int trap(int[] height) {
	    int length = height.length;
	    int res = 0;
	    for (int i = 1; i < length - 1; i++) {
	        int leftMax = 0, rightMax = 0;
	        //寻找左边最高的柱子
	        for (int j = i; j >= 0; j--) {
	            leftMax = Math.max(leftMax, height[j]);
	        }
	        //寻找右边最高的柱子
	        for (int j = i; j < length; j++) {
	            rightMax = Math.max(rightMax, height[j]);
	        }
	        //计算当前位置 i 处能够接的雨水量
	        res += Math.min(leftMax, rightMax) - height[i];
	    }
	    return res;
	} 
}

//思路2————双指针
class Solution {
    public static int trap(int[] height) {
        int res = 0;
        // left 和 right 分别指向数组首和数组尾的指针
        int left = 0;
        int right = height.length - 1;
        // leftMax 和 rightMax 分别表示左右两侧柱子的最高高度,初始值均为 0
        int leftMax = 0;
        int rightMax = 0;
        while (left < right) {
            leftMax = Math.max(leftMax, height[left]);
            rightMax = Math.max(rightMax, height[right]);
            if (leftMax < rightMax) {
                res += leftMax - height[left++];
            } else {
                res += rightMax - height[right--];
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值