力扣面试经典算法150题:接雨水

接雨水

今天的题目是力扣面试经典算法150题中的困难难度数组题目:分发糖果。

题目链接:https://leetcode.cn/problems/trapping-rain-water/description/?envType=study-plan-v2&envId=top-interview-150

题目描述

给定 n 个非负整数表示每个宽度为 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 个单位的雨水(蓝色部分表示雨水)。

题目分析

题目内容不多,主要还是看示例中的图片来进行分析。

首先题目会给定一个非负整数数组,数组的每个元素对应到坐标上的一个柱状图。如上图。

题目的要求是,我们需要计算出这个数组中可以容下多少单位的水。 注意Y坐标轴不参于接水。

对于题目的要求,比较考验空间想象能力以及空间计算能力。

解题思路

困难题目名不虚传啊,昨天的开胃菜一对比确实不难。

这个题目要解答主要有两个点需要确定。

  1. 我们首先要界定两个位置,确保这个两个位置可以接住水,比如示例中下标1到下标3中间可以接水,下标3到下标7又开始接水,下标8到下标10又可以接水。
  2. 确定边界位置以后,我们要计算能装多少水。注意,这里我们确定能装的水的数量,不能等确定两个边界后再算,这样比较难算,我们应该在每次向下获取下标值判定是否到边界时就应该把移动这个下标所能装的水的数量计算好。

思考到这里,其实方法已经出现了。没错,就是双指针法。

双指针法也是老演员了,数组题目可以说出现很多次了。

那么本题使用双指针法解答如下:

  1. 初始化指针:
    left 和 right 分别指向数组的起始位置和末尾位置。
    leftMax 和 rightMax 分别记录左侧和右侧的最大高度。
    water 用于累计总的雨水量。
  2. 移动指针:
    如果 heightleft < heightright,则移动左指针。
    否则,移动右指针。
  3. 更新最大高度:
    如果当前高度大于等于已知的最大高度,则更新最大高度。
    否则,当前位置可以接住的雨水量为最大高度减去当前位置的高度。
  4. 累计雨水量:
    将每次计算的雨水量累加到 water 中。

实际算法代码

以下是双指针法的代码实现:

java 复制代码
public class Solution {

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] height = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
        System.out.println(solution.trap(height)); // 输出 6
    }

    public int trap(int[] height) {
        if (height == null || height.length <= 2) {
            return 0;
        }

        int left = 0;
        int right = height.length - 1;
        int leftMax = 0;
        int rightMax = 0;
        int water = 0;

        while (left < right) {
            if (height[left] < height[right]) {
                // 如果左指针的高度小于右指针的高度
                if (height[left] >= leftMax) {
                    // 更新左侧最大高度
                    leftMax = height[left];
                } else {
                    // 左侧当前位置可以接住的雨水量
                    water += leftMax - height[left];
                }
                left++; // 移动左指针
            } else {
                // 如果右指针的高度小于等于左指针的高度
                if (height[right] >= rightMax) {
                    // 更新右侧最大高度
                    rightMax = height[right];
                } else {
                    // 右侧当前位置可以接住的雨水量
                    water += rightMax - height[right];
                }
                right--; // 移动右指针
            }
        }

        return water;
    }
}

结果

运行代码,输出结果符合预期:

提交到力扣,也通过测试:

总结

双指针法,用多很多次了,这里不再多废话讲。后面写一篇数组刷题总结。

还剩一题,加油!!!

相关推荐
白白白小纯15 小时前
算法篇—返回倒数第k个节点
c语言·数据结构·算法·leetcode
小羊先生car16 小时前
RTOS-F429-HAL-(动/静态)任务的创建(2026/7/27)
开发语言·算法·c#
无忧.芙桃16 小时前
数据结构之堆
c语言·数据结构·c++·算法·
桐薇全肯定16 小时前
MySQL学生成绩管理系统实战操作
java·数据库·sql
小蒋学算法16 小时前
算法-删除元素后最大固定点数目-典型最长增长序列算法
数据结构·算法
RD_daoyi16 小时前
Google偷偷给AI引用加了五个新功能:内联引用、悬停预览、品牌展示……但点击率真的回来了吗?
大数据·网络·人工智能·算法·安全·搜索引擎
船漏了就会沉16 小时前
后缀自动机(SAM):字符串处理的“万能瑞士军刀”
算法
Nuanyt16 小时前
SSM 学习记录 第二部分 Spring整合Mybatis&Junit AOP核心概念 Spring事务管理 SpringMVC 请求与响应 Rest风格
java·spring·junit·mybatis·restful
醉城夜风~16 小时前
C++模板详解:从基础到高级全面解析
java·开发语言·c++