【LeetCode力扣】42. 接雨水

news2024/12/22 22:09:11

目录

1、题目介绍

2、解题思路

2.1、暴力破解法

2.2、双指针法


 

 

1、题目介绍

原题链接: 42. 接雨水 - 力扣(LeetCode)

 示例 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

 提示:

  • n == height.length
  • 1 <= n <= 2 * 104
  • 0 <= height[ i ] <= 105 

2、解题思路

2.1、暴力破解法

首先看到这题的第一反应就是,通过每层遍历去找出蓝色块(即水块)。

只要找到每一层的边界,再通过右边界right - 左边界left + 1即可得出该层(蓝色块与黑色块)的总和,再通过遍历去掉黑色块,就能够得出单层的水块,最终将每一层水块累加则得出结果。

图解说明: 

第一层:

        通过计算找出第一层的边界,可以发现第一层的边界规律是,只要左边界left从左往右找到第一个大于等于1的柱子,即是左边界;而右边界right从右往左找到第一个大于等于1的柱子,即为右边界。再通过right - left + 1(即11-1+1 = 11)得到第一层所有所有区域总和len,然后从left进行遍历数组到right ,只要当前值大于等于1,则len自减1。最后减完之后得出的len即为第一层水块数。

第二层:

        同理,只要左边界left从左往右找到第一个大于等于2的柱子,即是左边界;而右边界right从右往左找到第一个大于等于2的柱子,即为右边界。再通过right - left + 1(即8)得到第二层所有所有区域总和len,然后从left进行遍历数组到right ,只要当前值大于等于2,则len自减1。最后减完之后得出的len即为第二层水块数。

第三层 :

        当边界left < right 时,循环结束,此时第三层的left等于right,直接退出循环,不需要计算。

 代码实现:

其中:

heightMax方法用于计算整个数组的最大值,也就是最大层数,最大层数有多少,就需要遍历多少次。

layerNumber方法用于计算每一层的水块个数。

class Solution {
    public int trap(int[] height) {
        int left = 0;
        int right = height.length - 1;
        int sum = 0;
        int max = heightMax(height);   //计算出最大层数
        for(int i = 1; i <= max; i++) {  //几层就循环几次
            if(left < right) {
                while(height[left] < i) {   //找出左边界
                    left++;
                }
                while(height[right] < i) {  //找出右边界
                    right--;
                }
                int ret = layerNumber(height,left,right,i);  //计算该层的水块
                sum += ret;  //sum记录水块个数
            }
        }
        return sum;
    }

    public int heightMax(int[] arr) {
        int max = arr[0];
        for(int i = 1; i < arr.length; i++) {
            max = max > arr[i] ? max : arr[i];
        }
        return max;
    }

    signal是当前所在层数
    public int layerNumber(int[] arr, int left, int right, int signal) {   
        int len = right - left + 1;   //画图理解+1
        for(int i = left; i <= right; i++) {
            if(arr[i] >= signal) {
                len--;
            }
        }
        return len;
    }
}

 但是由于是暴力破解,每层都需要依次遍历,因此时间复杂度和空间复杂度非常高。

下面给大家讲解一个巧妙运用双指针动态规划下快速计算出结果的算法。

2.2、双指针法

leftMax用于记录当前左指针left经过的最大高度,同理rightMax用于记录当前左指针right经过的最大高度。

下标 i 处能否接水以及接到水的数量其实取决于左指针left到 i 时所经过的最大高度leftMax右指针right到 i 时所经过的最大高度rightMax它们之间的较小值。

例如:

下标5处,它能接到水的数量是leftMax和rightMax的最小值减去下标 i 的高度。

再例如:

下标9处,它能接到水的数量是leftMax和rightMax的最小值减去下标 i 的高度。

代码实现: 

class Solution {
    public int trap(int[] height) {
        int left = 0;
        int right = height.length - 1;
        int leftMax = 0;
        int rightMax = 0;
        int sum = 0;
        while(left < right) {
            leftMax = Math.max(leftMax,height[left]);  //每次循环前判断最大值
            rightMax = Math.max(rightMax,height[right]); //每次循环前判断最大值
            //谁小移动谁,并且移动前计算当前位置与最大高度的差值,差值即水量数。
            if(leftMax > rightMax) {     
                sum += rightMax - height[right];
                right--;
            }else{    //相等时移动哪一个都可以,这里移动left
                sum += leftMax - height[left];
                left++;
            }
        }
        return sum;
    }
}

复杂度分析:

时间复杂度:O(n),其中 n 是数组 height 的长度。两个指针的移动总次数不超过 n。

空间复杂度:O(1)。只需要使用常数的额外空间。

使用该方法能够大大降低时间复杂度。

更多【LeetCode刷题】推荐:

【LeetCode力扣】189 53 轮转数组 | 最大子数组和-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/134095703?spm=1001.2014.3001.5502

【LeetCode力扣】234 快慢指针 | 反转链表 | 还原链表-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/133958602?spm=1001.2014.3001.5502 

【LeetCode力扣】86. 分隔链表-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/133942678?spm=1001.2014.3001.5502 

 

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

 

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

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

相关文章

Python打包成.exe文件直接运行

文章目录 前言pyinstaller.exe文件具体步骤第一步&#xff1a;安装pyinstaller第二步&#xff1a;进入要打包文件的目录第三步&#xff1a;执行文件第四步&#xff1a;发给好友 拓展尾声 前言 很多小伙伴在阅读了博主的文章后都积极与博主交流&#xff0c;在这里博主很感谢大家…

scrapy-redis分布式爬虫(分布式爬虫简述+分布式爬虫实战)

一、分布式爬虫简述 &#xff08;一&#xff09;分布式爬虫优势 1.充分利用多台机器的带宽速度 2.充分利用多台机器的ip地址 &#xff08;二&#xff09;Redis数据库 1.Redis是一个高性能的nosql数据库 2.Redis的所有操作都是原子性的 3.Redis的数据类型都是基于基本数据…

LED数码管的静态显示与动态显示(Keil+Proteus)

前言 就是今天看了一下书上的单片机实验&#xff0c;发现很多的器件在Proteus中都不知道怎么去查找&#xff0c;然后想做一下这个实验&#xff0c;尝试能不能实现&#xff0c;LED数码管的两个还可以实现&#xff0c;但是用LED点阵显示器的时候他那个网络标号不知道是什么情况&…

GZ035 5G组网与运维赛题第7套

2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项&#xff08;高职组&#xff09; 赛题第7套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通&#xff08;35分&#xff09; 子任务1&#xff1a;5G公共网络部署与调试&#xff08;15分&#xff09; 子…

python自动化测试(六):唯品会商品搜索-练习

目录 一、配置代码 二、操作 2.1 输入框“运动鞋” 2.2 点击搜索按钮 2.3 选择品牌 2.4 选择主款 2.5 适用性别 2.6 选择尺码 2.7 选择商品&#xff1a;&#xff08;通过css的属性去匹配&#xff09; 2.8 点击配送地址选项框 一、配置代码 # codingutf-8 from selen…

基于萤火虫算法的无人机航迹规划-附代码

基于萤火虫算法的无人机航迹规划 文章目录 基于萤火虫算法的无人机航迹规划1.萤火虫搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用萤火虫算法来优化无人机航迹规划。 1.萤火虫…

Mysql数据库基本概念和Sql语言

一、数据库基本概念 1.1 数据库概述 数&#xff1a;数字信息 据&#xff1a;属性 数据&#xff1a;对一系列对象的具体属性的描述的集合 数据库&#xff1a;数据库就是用来组织(各个数据之间是有关联的&#xff0c;按照规则组织起来的)、存储和管理(对数据的增、删、改、查)的…

JavaEE-博客系统1(数据库和后端的交互)

本部分内容包括网站设计总述&#xff0c;数据库和后端的交互&#xff1b; 数据库操作代码如下&#xff1a; -- 编写SQL完成建库建表操作 create database if not exists java_blog_system charset utf8; use java_blog_system; -- 建立两张表&#xff0c;一个存储博客信息&am…

数据结构—线性实习题目(二)5迷宫问题(栈)

迷宫问题&#xff08;栈&#xff09; #include <iostream>​ #include <assert.h> using namespace std;int qi1, qi2; int n; int m1, p1; int** Maze NULL; int** mark NULL;struct items {int x, y, dir; };struct offsets {int a, b;char* dir; };const int…

Java SE 学习笔记(十八)—— 注解、动态代理

目录 1 注解1.1 注解概述1.2 自定义注解1.3 元注解1.4 注解解析1.5 注解应用于 junit 框架 2 动态代理2.1 问题引入2.2 动态代理实现 1 注解 1.1 注解概述 Java 注解&#xff08;Annotation&#xff09;又称Java标注&#xff0c;是JDK 5.0引入的一种注释机制&#xff0c;Java语…

Java 基于微信小程序的汉堡点餐系统的研究与实现

文章目录 1 简介2 相关技术介绍3 系统需求分析4 系统功能分析5 系统的详细设计与实现5.1 系统登录页面5.2 点餐系统后台首页页面5.3 商品信息管理页面5.4 会员管理页面5.5 购买信息管理页面5.6 小程序首页信息页面5.7 商品信息页面5.8 在线下单页面 6 推荐阅读 1 简介 基于微信…

笔记本电脑搜索不到wifi6 无线路由器信号

路由器更换成wifi6 无线路由器后&#xff0c;手机能搜索到这个无线信号&#xff0c;但是笔记本搜索不到这个无线信号&#xff0c;后网上搜索后发现是无线网卡驱动问题&#xff0c;很多无线网卡使用的是Intel芯片&#xff0c;Intel就此发布了公告&#xff0c;升级驱动就可以彻底…

【C】C语言文件操作

1.为什么使用文件 我们前面学习结构体时&#xff0c;写通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c;可以给通讯录中增加、删除数据&#xff0c;此时数据是存放在内存中&#xff0c;当程序退出的时候&#xff0c;通讯录中的数据自然就不存在了&#xff0c;等下…

ZYNQ连载08-Lwip网络组件

ZYNQ连载08-Lwip网络组件 1. 添加Lwip包 2. Lwip配置 我这里关闭ipv6和dhcp。 3. tcp客户端 #include "include/my_tcp.h" #include "lwip/ip.h"#define THREAD_STACKSIZE 1024 #define SERVER_PORT 8000 #define SERVER_ADDR "192.168.3.190&qu…

SHCTF2023 山河CTF Reverse方向week2weenk3部分WP【详解】

文章目录 [WEEK3]ststst[WEEK2]not gcc[WEEK2]Run?润&#xff01;[WEEK2]Authurs_box[WEEK2]pycode [WEEK3]ststst 64 bit 的 ELF 文件 sub_400763点进去看看 mprotect &#xff0c;这个 这一题是SMC TEA的考察&#xff0c;我写过一篇关于 SMC学习网鼎杯jocker 可以使用id…

设计模式(单例模式、工厂模式及适配器模式、装饰器模式)

目录 0 、设计模式简介 一、单例模式 二、工厂模式 三、适配器模式 四、装饰器模式 0 、设计模式简介 设计模式可以分为以下三种: 创建型模式&#xff1a;用来描述 “如何创建对象”&#xff0c;它的主要特点是 “将对象的创建和使用分离”。包括单例、原型、工厂方法、…

LabVIEW开发安捷伦液相色谱Agilent 1100 HPLC

LabVIEW开发安捷伦液相色谱Agilent 1100 HPLC 液相色谱是在科研中常用的仪器&#xff0c;尤其是安捷伦等大品牌。这里对1100的使用进行介绍。 LabVIEW安捷伦1100系列驱动程序&#xff0c;用于控制1100系列的所有仪器。在LabVIEW中使用串行&#xff0c;GPIB或以太网接口。参考…

【java爬虫】公司半年报数据展示

前言 前面有一篇文章介绍了使用selenium获取上市公司半年报的方法&#xff0c;这篇文章就给这些数据写一个简单的前端展示页面 上一篇文章的链接在这里 【java爬虫】使用selenium获取某交易所公司半年报数据-CSDN博客 首先来看一下整个页面的展示效果 前端页面采用vueeleme…

第89步 时间序列建模实战:时间序列融合模型

基于WIN10的64位系统演示 一、写在前面 这一期&#xff0c;我们介绍融合模型模型。 &#xff08;1&#xff09;数据源&#xff1a; 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Renal Syndro…

创建进程中的内核操作

fork 是一个系统调用&#xff0c;流程的最后会在 sys_call_table 中找到相应的系统调用 sys_fork。 _do_fork 里面做的第一件大事就是 copy_process&#xff0c;咱们前面讲过这个思想。如果所有数据结构都从头创建一份太麻烦了&#xff0c;还不如使用惯用“伎俩”&#xff0c;…