力扣面试经典算法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. 移动指针:
    如果 height[left] < height[right],则移动左指针。
    否则,移动右指针。
  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;
    }
}

结果

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

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

总结

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

还剩一题,加油!!!

相关推荐
南山十一少2 小时前
Spring Security+JWT+Redis实现项目级前后端分离认证授权
java·spring·bootstrap
427724004 小时前
IDEA使用git不提示账号密码登录,而是输入token问题解决
java·git·intellij-idea
chengooooooo4 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
李长渊哦4 小时前
常用的 JVM 参数:配置与优化指南
java·jvm
计算机小白一个4 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
万事可爱^5 小时前
HDBSCAN:密度自适应的层次聚类算法解析与实践
算法·机器学习·数据挖掘·聚类·hdbscan
大数据追光猿7 小时前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法
Dream it possible!7 小时前
LeetCode 热题 100_在排序数组中查找元素的第一个和最后一个位置(65_34_中等_C++)(二分查找)(一次二分查找+挨个搜索;两次二分查找)
c++·算法·leetcode
夏末秋也凉7 小时前
力扣-回溯-46 全排列
数据结构·算法·leetcode
南宫生7 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode