LeetCode:42. 接雨水

简介

题目链接:https://leetcode.cn/problems/trapping-rain-water/description/

解决方式:数组 + 暴力枚举 / 动态规划 / 双指针

这是作者学习众多大神的思路进行解题的步骤,很推荐大家解题的时候去看看题解里面大佬们的思路、想法!

暴力枚举

思路:对于"接雨水"问题,暴力枚举的思路非常直观:对于每个柱子,它上方能接的雨水量取决于它左边最高柱子和右边最高柱子中的较小者,再减去它自身的高度。如果这个差值是正数,就说明能积水。

java 复制代码
class Solution {
    public int trap(int[] height) {
        // 结果
        int water = 0;
        // 迭代
        for(int i = 0; i < height.length; i++){
            // 当前柱子高度
            int h = height[i];
            // 向左寻找左侧最高元素(包括当前元素)
            int leftHeight = 0;
            for(int left = 0; left <= i; left++){
                leftHeight = Math.max(leftHeight, height[left]);
            }
            // 向右寻找右侧最高元素(包括当前元素)
            int rightHeight = 0;
            for(int right = i; right < height.length; right++){
                rightHeight = Math.max(rightHeight, height[right]);
            }
            // 公式。两侧较小元素值减去当前元素值
            int w = Math.min(leftHeight, rightHeight) - h;
            // 结果大于零,则可以接雨水
            if(w > 0){
                water += w;
            }
        }
        // 返回结果
        return water;
    }
}

动态规划

思路:暴力枚举的方法由于查找左右两侧最大元素时都是从零开始,所以时间开销太大。我们可以通过记忆化的方式对其进行优化。当前元素的左侧最大值是前一个元素的左侧最大值与当前元素进行比较后的最大值,同理,右侧最大值是下一个元素的右侧最大值与当前元素进行比较后的最大值。我们可以先通过两个循环将左右两侧的最大值计算出来,后续迭代数组的时候就不用再进行计算了,也防止了重复计算的可能。

java 复制代码
class Solution {
    public int trap(int[] height) {
        // 总水量
        int totalWater = 0;
        // 数组每一元素的左侧最大值数组
        int[] leftMax = new int[height.length];
        leftMax[0] = height[0];
        for(int i = 1; i < height.length; i++){
            leftMax[i] = Math.max(leftMax[i - 1], height[i]);
        }
        // 数组每一个元素右侧的最大值数组
        int[] rightMax = new int[height.length];
        rightMax[height.length - 1] = height[height.length - 1];
        for(int i = height.length - 2; i >= 0; i--){
            rightMax[i] = Math.max(rightMax[i + 1], height[i]);
        }
        // 迭代数组
        for(int i = 0; i < height.length; i++){
            int water = Math.min(leftMax[i], rightMax[i]) - height[i];
            if(water > 0){
                totalWater += water;
            }
        }
        // 返回结果
        return totalWater;
    }
}

双指针

思路:动态规划会预先将左右两侧的最大值计算并存储下来,会有一定的空间开销。我们可以借助双指针,边迭代边计算,进行进一步的优化。双指针,一个指针指向数组左侧,一个指针指向数组右侧。循环过程中,每次只会移动一个指针。移动左指针,则说明右侧最大值比左侧最大值大,左指针指向的元素的水量取决于左侧最大值。同理,移动右指针,则说明左侧最大值大于等于右侧最大值,右指针指向的元素的水量取决于右侧最大值。

java 复制代码
class Solution {
    public int trap(int[] height) {
        // 总水量
        int totalWater = 0;
        // 双指针
        int left = 0;
        int right = height.length - 1;
        // 两侧最大值
        int leftMax = 0;
        int rightMax = 0;
        // 迭代数组
        while(left < right){
            // 右侧最大值大于左侧最大值
            if(height[left] < height[right]){
                // 水量由左侧最大值决定
                if(height[left] >= leftMax){
                    // 此时左侧最大值 - 当前元素 <= 0(当前元素最大),无法接水
                    // 更新左侧最大值
                    leftMax = height[left];
                }else{
                    // 此时左侧最大值 - 当前元素 > 0,可以接水
                    totalWater += leftMax - height[left];
                }
                // 移动左指针
                left++;
            }else{
                // 左侧最大值大于等于右侧最大值
                // 水量由右侧最大值决定
                if(height[right] >= rightMax){
                    // 此时右侧最大值 - 当前元素 <= 0(当前元素最大),无法接水
                    // 更新右侧最大值
                    rightMax = height[right];
                }else{
                    // 此时右侧最大值 - 当前元素 > 0,可以接水
                    totalWater += rightMax - height[right];
                }
                // 移动右指针
                right--;
            }
        }
        // 返回结果
        return totalWater;
    }
}
相关推荐
JieE2121 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
JieE2122 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack203 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树3 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2123 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2123 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术3 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦3 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户497863050734 天前
(一)小红的数组操作
算法·编程语言