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;
    }
}
相关推荐
lixinnnn.2 小时前
01BFS:小明的游戏
算法
falldeep2 小时前
Claude Code源码分析
人工智能·算法·机器学习·强化学习
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2026.04.14 题目:2463.最小移动距离
笔记·算法·leetcode
feng_you_ying_li2 小时前
C++11可变模板参数,包扩展,emplace系列和push系列的区别
前端·c++·算法
tankeven2 小时前
HJ177 可匹配子段计数
c++·算法
剑挑星河月2 小时前
55.跳跃游戏
数据结构·算法·leetcode
Gofarlic_OMS2 小时前
中小企业控制方法:中小型制造企业Creo许可证成本控制
java·大数据·运维·算法·matlab·制造
星马梦缘2 小时前
快表、页表地址获取+缓存、主存、硬盘数据获取
算法·操作系统·os·tlb