力扣第42题 接雨水

news2024/11/17 7:34:30

前言

记录一下刷题历程 力扣第42题 接雨水


接雨水

原题目:给定 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

分析

我们首先可以想到的就是统计一列左边和右边所有柱子的最高高度,根据下图我们可以知道左右最高高度较低的值与当前柱子的高度差就是这一列能存储的水的高度。这是第一种方法但是需要O(n)的空间复杂度,有没有优化空间呢,我们来看方法2.
在这里插入图片描述
第二种方法,我们其实并不需要同时计算左右两边的最高高度,假如说我们对于当前列已经知道了左侧的最高高度,只要右侧出现比左侧高度还要高,那么左侧的最高高度就一定是水体的顶部,然后我们可以计算该列的水体高度,我们从数组两端向中间遍历,分别计算左指针和左侧最高高度,右指针和右侧最高高度,找到对应结果较低的那一列直接更新结果即可

代码如下:

第一种方法:

class Solution {
public:
    // 接收一个整数数组 height,表示每个柱子的高度,返回可以接住的雨水总量
    int trap(vector<int>& height) {
        // n 表示柱子的总数
        int n = height.size();
        // res 用于存储最终结果,也就是可以接住的雨水总量
        int res = 0;

        // 创建两个数组,分别存储每个位置的左边最高柱子和右边最高柱子
        vector<int> leftMax(n);  // leftMax[i] 表示位置 i 左边最高的柱子
        vector<int> rightMax(n); // rightMax[i] 表示位置 i 右边最高的柱子

        // 初始化 leftMax 数组的第一个元素,因为第 0 个位置没有左边的柱子,所以 leftMax[0] 就是 height[0]
        leftMax[0] = height[0];

        // 计算每个位置的左边最高柱子,从左到右遍历
        for(int i = 1; i < n - 1; i++) {
            // leftMax[i] 是当前位置 i 和位置 i-1 的最高柱子之间的较大值
            leftMax[i] = max(leftMax[i - 1], height[i]);
        }

        // 初始化 rightMax 数组的最后一个元素,因为最后一个位置没有右边的柱子,所以 rightMax[n-1] 就是 height[n-1]
        rightMax[n - 1] = height[n - 1];

        // 计算每个位置的右边最高柱子,从右到左遍历
        for(int i = n - 2; i > 0; i--) {
            // rightMax[i] 是当前位置 i 和位置 i+1 的最高柱子之间的较大值
            rightMax[i] = max(rightMax[i + 1], height[i]);
        }

        // 遍历每个柱子,计算该柱子上方能够接住的雨水
        for(int i = 1; i < n - 1; i++) {
            // 当前位置的雨水容量等于左边和右边最高柱子之间的较小值减去当前柱子的高度
            int capacity = min(leftMax[i], rightMax[i]) - height[i];
            // 累加结果,capacity 是该位置能接住的水
            res += capacity;
        }

        // 返回最终的接水量
        return res;
    }
};

第二种方法:

class Solution {
public:
    int trap(vector<int>& height) {
        // 获取柱子的总数
        int n = height.size();
        // 如果柱子数小于3,无法接住雨水,直接返回0
        if (n < 3) return 0;
        
        // 结果变量,用于存储接住的雨水总量
        int res = 0;
        // 左指针初始化为数组的起始位置
        int left = 0;
        // 右指针初始化为数组的结束位置
        int right = n - 1;
        // 左边最大值初始化为0
        int leftMax = 0;
        // 右边最大值初始化为0
        int rightMax = 0;
        
        // 双指针遍历,直到两个指针重合
        while (left < right) {
            // 更新左边最大值
            leftMax = max(leftMax, height[left]);
            // 更新右边最大值
            rightMax = max(rightMax, height[right]);
            
            // 如果左边最大值小于右边最大值,处理左边的情况
            if (leftMax < rightMax) {
                // 当前位置的水量 = 左边最大值 - 当前柱子的高度
                res += leftMax - height[left];
                // 左指针向右移动
                left++;
            } 
            // 如果右边最大值小于等于左边最大值,处理右边的情况
            else {
                // 当前位置的水量 = 右边最大值 - 当前柱子的高度
                res += rightMax - height[right];
                // 右指针向左移动
                right--;
            }
        }
        // 返回接住的雨水总量
        return res;
    }
};

代码解释

第一种方法主要思路:

1.对于每个柱子而言,能接住的水量取决于左边最高的柱子和右边最高的柱子,以及当前位置柱子的高度。柱子能接住的水量是左、右柱子中较矮的那个减去当前柱子的高度。

为了快速得到每个柱子左边和右边的最大值,我们通过预处理分别计算 leftMax 和 rightMax 数组。然后对于每个柱子,计算它上方可以接住的水量并累加到结果中。

2.首先,我们用两个数组 leftMax 和 rightMax 分别记录每个柱子左边和右边的最高柱子。

leftMax[i] 表示位置 i 左边的最高柱子,包括 i 本身。
rightMax[i] 表示位置 i 右边的最高柱子,包括 i 本身。

3.遍历 height 数组计算每个位置的左边最高值和右边最高值。

对于每个位置的柱子,我们计算其能接住的雨水量:min(leftMax[i], rightMax[i]) - height[i]。
累加每个位置的水量得到最终结果。

复杂度分析:

时间复杂度:该算法需要遍历三次数组,时间复杂度为 O(n)。
空间复杂度:需要额外的两个数组存储左边和右边的最大值,空间复杂度为 O(n)。
这就是该算法的基本思路和实现方式。

第二种方法主要思路:

1.初始化:

获取 height 数组的大小 n,存储在变量 n 中。
如果柱子的数量小于3(例如0、1或2个柱子),无法形成凹槽来接雨水,直接返回0。
初始化结果变量 res 为0,用于存储计算得到的雨水总量。
初始化两个指针 left 和 right 分别指向数组的起始和结束位置。
初始化 leftMax 和 rightMax 为0,用于记录当前左边和右边的最大高度。

2.双指针遍历:

当 left 指针小于 right 指针时进行循环。
在每次循环中:
更新 leftMax 为当前位置左指针所指柱子的高度与之前 leftMax 的最大值之间的较大值。
更新 rightMax 为当前位置右指针所指柱子的高度与之前 rightMax 的最大值之间的较大值。

如果 leftMax 小于 rightMax,说明左边的最高柱子更矮,处理左边的情况:

计算当前位置可以接住的雨水量,等于 leftMax 减去当前柱子的高度。
将该雨水量累加到结果变量 res 中。
将左指针向右移动一位。

否则,说明右边的最高柱子更矮或相等,处理右边的情况:

计算当前位置可以接住的雨水量,等于 rightMax 减去当前柱子的高度。
将该雨水量累加到结果变量 res 中。
将右指针向左移动一位。

3.返回结果:

循环结束后,返回最终计算得到的接水总量 res。

复杂度分析

时间复杂度:该算法的时间复杂度为 O(n),因为每个柱子位置在循环中只会被访问一次。
空间复杂度:该算法的空间复杂度为 O(1),仅使用了常量级的额外空间,不需要额外的数组。
这个双指针方法在时间复杂度和空间复杂度上都具有较好的性能,是处理这个问题的一种高效解法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二进制方式部署K8s高可用集群

1 二进制方式部署K8s高可用集群 1.1 kubeadm 和二进制安装 k8s 适用场景分析 kubeadm 是官方提供的开源工具&#xff0c;是一个开源项目&#xff0c;用于快速搭建 kubernetes 集群&#xff0c;目前是比较方便和推荐使用的。kubeadm init 以及 kubeadm join 这两个命令可以快速…

MySQL—死锁

什么是死锁&#xff1f; 好比是两个事务都在等待对方释放锁&#xff0c;之后进行下一步操作&#xff0c;但是最后双方都没有释放资源&#xff0c;所以导致一直处于等待的状态。 但是服务器不会让死锁的状态一直持续&#xff0c;会关闭其中一个影响较小的事务&#xff08;右边的…

紫光展锐完成Android 15同步升级,驱动技术创新与生态共赢

近日&#xff0c;紫光展锐宣布&#xff0c;展锐5G移动平台T820、T770、T765、T760、T750以及4G平台T620、T619、T616、T615、T612、T606&#xff0c;完成Android 15同步升级。相较于过往Android发布&#xff0c;今年同步升级Android 15主要有三大提升&#xff1a; ■ 紫光展锐实…

SaToken认证授权快速上手

SA-TOKEN认证授权快速上手 SaToken简介认证授权实现1 创建5张测试基础表2 配置文件3 Sa-Token的全局拦截器4 自定义权限认证接口扩展5 SaToken用户控制层 测试验证用户2登录验证权限用户1登录验证权限项目代码结构 SaToken简介 SaToken 是一个轻量级 Java 权限认证框架&#x…

【信号】信号的产生

信号的概念 什么是信号&#xff1f;我们生活中的红绿灯&#xff0c;闹钟&#xff0c;外面电话等等这些都是信号&#xff0c;我们是怎么认识这些信号的&#xff0c;我们认识这些信号&#xff0c;并且知道这些信号的处理方法&#xff0c;对于进程来说&#xff0c;也会认识相应的…

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么&#xff1f; K8s的架构原理 控制平面(Control plane) kube-apiserver etcd kube-scheduler kube-controller-manager cloud-controller-manager 小结 节点组件(Node) container runtime Pod kubelet ku…

Chrome、Edge、360及Firefox浏览器加载多个ActiveX插件的介绍

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

vc-align源码分析 -- ant-design-vue系列

vc-align源码分析 源码地址&#xff1a;https://github.com/vueComponent/ant-design-vue/tree/main/components/vc-align 1 基础代码 1.1 名词约定 需要对齐的节点叫source&#xff0c;对齐的目标叫target。 1.2 props 提供了两个参数&#xff1a; align&#xff1a;对…

成为优秀程序员-代码篇

1. 序言 刚毕业参加工作时候&#xff0c;公司正在快速扩张&#xff0c;我入职的时候组内刚刚招了一大波人&#xff0c;当时leader提出集体cr代码来拉齐团队内的编码规范&#xff0c;每当有对于相对重要改动大的项目就会集体cr代码&#xff0c;老板想法初衷是好的&#xff0c;但…

esp32 gpio 初始化不同类型的管脚,产生脉冲,发生中断

硬件&#xff1a;D4与D18 连接&#xff0c;二极管接D15与3.3v脚 图片 二极管同期性点亮&#xff0c;间隔1秒 参考esp32官网程序&#xff0c;从此程序可以看出&#xff0c;中断程序没有处理任何数据&#xff0c;只是把中断发生的事件存入队列。而用另一新线程来处理中断事务。…

GNSS CTS GNSS Start and Location Flow of Android15

目录 1. 本文概述2.CTS 测试3.Gnss Flow3.1 Gnss Start Flow3.2 Gnss Location Output Flow 1. 本文概述 本来是为了做Android 14 Gnss CTS 的相关环境的搭建和测试&#xff0c;然后在测试中遇到了一些问题&#xff0c;去寻找CTS源码(/cts/tests/tests/location/src/android/l…

Vue3-05_组件高级

背景 对组件的进一步了解,如组件之间通信等知识点&#xff0c;根据教程实现购物车功能&#xff0c;并修复原本的bug. watch 侦听器 用途 watch 侦听器允许开发者监视数据的变化&#xff0c;从而针对数据的变化做特定的操作。例如&#xff0c;监视用户名的变化并发起请求&am…

大模型AI一体机对行业的帮助

大模型AI一体机&#xff0c;如AntSKPro AI离线知识库一体机&#xff0c;是专门为企业和机构设计的集成系统&#xff0c;旨在提供高效的人工智能服务。这类一体机通常包含预训练的大型机器学习模型&#xff0c;以及必要的硬件和软件资源&#xff0c;以支持复杂的数据处理和分析任…

maven 编译构建可以执行的jar包

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

网易云音乐歌单下载器

最近要帮小朋友下载一些小学的诗词mp3&#xff0c;找了各种工具&#xff0c;还是这个好使 yun-playlist-downloader: 网易云音乐歌单下载器 特性 支持歌单 / 专辑 / 电台音质选择下载超时 / 重试再次下载默认跳过已下载部分, 使用 content-length 匹配自定义文件名下载进度显…

【代码随想录训练营第42期 Day53打卡 - 图论Part4 - 卡码网 110. 字符串接龙 105. 有向图的完全可达性

目录 一、个人感受 二、题目与题解 题目一&#xff1a;卡码网 110. 字符串接龙 题目链接 题解&#xff1a;BFS哈希 题目二&#xff1a;卡码网 105. 有向图的完全可达性 题目链接 题解&#xff1a;DFS 三、小结 一、个人感受 对于两大基本搜索&#xff1a; 深度优先搜…

JDBC:连接数据库

文章目录 报错 报错 Exception in thread “main” java.sql.SQLException: Can not issue SELECT via executeUpdate(). 最后这里输出的还是地址&#xff0c;就是要重写toString()方法&#xff0c;但是我现在还不知道怎么写 修改完的代码&#xff0c;但是数据库显示&#…

WebGL系列教程二(环境搭建及初始化Shader)

目录 1 前言2 新建html页面3 着色器介绍3.1 顶点着色器、片元着色器与光栅化的概念3.2 声明顶点着色器3.3 声明片元着色器 4 坐标系(右手系)介绍5 着色器初始化5.1 给一个画布canvas5.2 获取WebGL对象5.3 创建着色器对象5.4 获取着色器对象的源5.5 绑定着色器的源5.6 编译着色器…

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页&#xff1a;https://tangyuan96.github.io/minigpt_3d_project_page/ 代码&#xff1a;https://github.com/TangYuan96/MiniGPT-3D 论文&#xff1a;https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA&#xff0c;被ACM MM2024接收&#xff0c;只拥…

佰朔资本:9月首选行业为汽车、电子、医药生物等

5—8月商场接连调整&#xff0c;9月开端进入成绩空窗期&#xff0c;流动性和政策改动从头成为商场中心驱动力&#xff0c;风格切换先行&#xff0c;对当时的商场能够豁达一些。价值和生长风格切换的拐点开始闪现&#xff0c;生长相对价值的成绩优势开端走扩&#xff0c;美联储降…