力扣---接雨水---单调队列+动态规划+双指针

题目:

单调队列思想:

没有思路的小伙伴可以先把这个想清楚哦:力扣hot10---大根堆+双端队列-CSDN博客

从上面的图就可以发现,如果柱子呈递减序列,那么不会接到雨水,只要有一个小凸起柱子,那么这个柱子就会和之前的柱子接到雨水。所以我们维护一个递减序列,如果遍历到某个柱子接到雨水时,就把前面比他矮的柱子pop掉,同时因为接到了雨水,前面的柱子高度也会发生变化,变成了接完雨水后的最高值(height数组中的元素值需改变的原因为:考虑到后面还会有更高的柱子使得该柱子再次接到点雨水,我们需要改变柱子的长度)。一个柱子能接雨水的最大值该怎么求呢?首先,我们比较遍历到的这个柱子和队列中第一高的柱子哪个更低,如果该值为lower,那么接到的雨水部分英文lower-height[ i ]。不清晰的友友直接看代码吧~

代码:

C++:

class Solution {
public:int calculate(vector<int>& height,int idx_r,int idx_l){int s=0;int min_=min(height[idx_l],height[idx_r]);int r=height[idx_r];for(int i=idx_l;i<idx_r;i++){if(r>height[i]){s+=min_-height[i];height[i]=min_;}}return s;}int trap(vector<int>& height) {//单调队列(维护递减的序列)deque<pair<int,int>> q;int len=height.size();int s=0;for(int i=0;i<len;i++){//出while(!q.empty() and q.back().first<=height[i]){s+=calculate(height,i,q.front().second); //计算新加的面积大小,同时改变数组中的元素,因为已经接了雨水q.pop_back();}//进q.push_back({height[i],i});}return s;}
};

Python:

class Solution:def calculate(self,height:List[int],idx_r:int,idx_l:int) -> int:s=0min_=min(height[idx_l],height[idx_r])r=height[idx_r]for i in range(idx_l,idx_r):if r>height[i]:s+=min_-height[i]height[i]=min_return sdef trap(self, height: List[int]) -> int:q=deque()height_len=len(height)s=0for i in range(height_len):while q and q[-1][0]<=height[i]:s+=self.calculate(height,i,q[0][1])q.pop()q.append((height[i],i))return s

动态规划思想:

题解说是直觉(然后用动态规划来优化),我是真没有这直觉呀(...)

初始想法写到代码里面啦,这里再贴一遍:

初始想法:对于每个height[i],所接的雨水量等于该柱子左面的所有柱子高度最大值,以及
该柱子右面的所有柱子高度最大值,这两个值取较小的那一个,并减去该柱子原有的高度。

代码如下(直觉版):

class Solution {
public:int trap(vector<int>& height) {//初始想法:对于每个height[i],所接的雨水量等于该柱子左面的所有柱子高度最大值,以及//该柱子右面的所有柱子高度最大值,这两个值取较小的那一个,并减去该柱子原有的高度int len=height.size();int res=0;for(int i=0;i<len;i++){int maxl=0;int maxr=0;for(int j=0;j<i;j++){maxl=max(maxl,height[j]);}for(int j=i+1;j<len;j++){maxr=max(maxr,height[j]);}int temp=min(maxl,maxr)-height[i];if(temp>0){res+=temp;}}return res;}
};

但是!!!有一个点是过不去的,那么我们继续用动态规划思想来优化。

 既然代码中有这样一个过程,是不是感觉有很多地方做了无用功?为什么遍历每一个height[i]时都要计算左右的最大值呢,不能一次性记录嘛?(感觉有点前缀和思想)

for(int i=0;i<len;i++){int maxl=0;int maxr=0;for(int j=0;j<i;j++){maxl=max(maxl,height[j]);}for(int j=i+1;j<len;j++){maxr=max(maxr,height[j]);}
}

代码如下(动态规划版):

C++:

class Solution {
public:int trap(vector<int>& height) {//初始想法:对于每个height[i],所接的雨水量等于该柱子左面的所有柱子高度最大值,以及//该柱子右面的所有柱子高度最大值,这两个值取较小的那一个,并减去该柱子原有的高度int len=height.size();int res=0;vector<int> maxl(len,0);vector<int> maxr(len,0);for(int i=1;i<len;i++){maxl[i]=max(maxl[i-1],height[i-1]);}for(int i=len-2;i>=0;i--){maxr[i]=max(maxr[i+1],height[i+1]);}for(int i=0;i<len;i++){int temp=min(maxl[i],maxr[i])-height[i];if(temp>0){res+=temp;}}return res;}
};

Python:

class Solution:def trap(self, height: List[int]) -> int:len_height=len(height)res=0maxl=[0]*len_heightmaxr=[0]*len_heightfor i in range(1,len_height):maxl[i]=max(maxl[i-1],height[i-1])for i in range(len_height-2,-1,-1):maxr[i]=max(maxr[i+1],height[i+1])for i in range(len_height):temp=min(maxl[i],maxr[i])-height[i]if temp>0:res+=tempreturn res

双指针思路:

感觉题解说的有点迷(没太看懂,,)

先借用一下题解中的图:

首先我们先来看第一张图,由 i 和 j 两个指针,因为height[ j ]>height[ i ],所以 i 和 i 的右侧(直到 j )都可以接到雨水,右侧图片同理。有没有一点眼熟,把两个指针放到两侧,那个高度小于对方高度了,就像中间移动。有点像这道题:力扣---接雨水---单调队列-CSDN博客

我们还是看左面这张图,我们将指针 i 左侧的最高柱子高度记为MaxLeft,将指针 j 右侧的最高柱子高度记为MaxRight,我们就可以得到柱子 i 接到的雨水=MaxLeft-height[ i ]。???为什么就确定柱子 i 左侧的最大值一定小于右侧的最大值呢???右侧已经出现了一个较大的柱子 j 了,如果height[ i ]>height[ j ],那么说明 j 柱子是可以接到雨水的,那么 i 指针也不会向右移动,反而是 j 指针向左移动,所以如果柱子 i 左侧的最大值大于右侧的最大值的话,我们应该计算的是柱子 j 接到的雨水了(=MaxRight-height[ j ],因为左侧柱子已经足够高)!很绕很绕很绕。。。

代码如下:

class Solution {
public:int trap(vector<int>& height) {//初始想法:对于每个height[i],所接的雨水量等于该柱子左面的所有柱子高度最大值,以及//该柱子右面的所有柱子高度最大值,这两个值取较小的那一个,并减去该柱子原有的高度int len=height.size();int res=0;int MaxLeft=0;int MaxRight=0;int left=0;int right=len-1;while(left<right){MaxLeft=max(MaxLeft,height[left]);MaxRight=max(MaxRight,height[right]);if(height[left]<height[right]){res+=MaxLeft-height[left];left++;}else{res+=MaxRight-height[right];right--;}}return res;}
};

Python代码和C++类似,就不附啦~

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

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

相关文章

智慧城市的前景:数字孪生技术在智慧城市中的应用前景

目录 一、引言 二、数字孪生技术及其在智慧城市中的应用概述 三、数字孪生技术在智慧城市中的应用前景 1、城市规划与仿真模拟 2、智能交通与出行服务 3、智慧环保与可持续发展 4、智慧公共服务与社会治理 5、智慧能源与绿色建筑 四、数字孪生技术在智慧城市中的挑战与…

SpringCloud(21)之SpringCloud Alibaba Nacos实战应用

一、Nacos安装 1.1 Nacos概述 Nacos是Alibaba微服务生态组件中的重要组件之一&#xff0c;主要用它实现应用的动态服务发现、配置管理、 服务管理。Nacos discovery alibaba/spring-cloud-alibaba Wiki GitHub Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简…

Oracle.xs.dll‘ for module DBD::Oracle: load_file:找不到指定的模块

安装Ora2pg时,碰到 异常现象 D:\ProgramFiles\ora2pg>ora2pg -t show_report --estimate_cost -c ora2pg_conf.dist install_driver(Oracle) failed: Cant load D:/ProgramFiles/strawberry/perl/site/lib/auto/DBD/Oracle/Oracle.xs.dll for module DBD::Oracle: load_fil…

vulhub靶场-matrix-breakout-2-morpheus

下载&部署 从官网中下载 https://www.vulnhub.com/entry/matrix-breakout-2-morpheus,757/ 下载完成后&#xff0c;在vmware中打开&#xff0c;选择刚刚下载的ova文件 vmware打开文件后需要将刚导入的机器重新启动 再检查下网卡是否是和kali在同一张网卡下就可以开始打靶了…

设计模式学习笔记 - 规范与重构 - 5.如何通过封装、抽象、模块化、中间层解耦代码?

前言 《规范与重构 - 1.什么情况下要重构&#xff1f;重构什么&#xff1f;又该如何重构&#xff1f;》讲过&#xff0c;重构可以分为大规模高层重构&#xff08;简称 “大型重构”&#xff09;和小规模低层次重构&#xff08;简称 “小型重构”&#xff09;。大型重构是对系统…

谷粒商城【成神路】-【10】——缓存

目录 &#x1f9c2;1.引入缓存的优势 &#x1f953;2.哪些数据适合放入缓存 &#x1f32d;3.使用redis作为缓存组件 &#x1f37f;4.redis存在的问题 &#x1f9c8;5.添加本地锁 &#x1f95e;6.添加分布式锁 &#x1f95a;7.整合redisson作为分布式锁 &#x1f697…

【教程】使用小米换机来迁移数据

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 1、在新旧手机上都下载安装小米换机app&#xff1a;小米换机-小米应用商店 2、在新手机上&#xff0c;选择旧手机类型 3、授予权限 4、在旧手机上&#xff0c;授予权限 4、输入锁屏密码 5、选择发现的新手机 6、等…

EMC整改

EMC包括EMI和EMS&#xff0c;其中EMI由辐射干扰RE、传导干扰CE、谐波电流Harmonics、闪烁Flicker组成&#xff0c;EMS由静电抗扰度ESD、电快速瞬态脉冲群EFT、电压跌落DIP、传导抗扰度CS、辐射抗扰度RS、浪涌抗扰度surge、工频磁场抗扰度PMS。新产品生产出来但凡要做认证&#…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:NavDestination)

作为子页面的根容器&#xff0c;用于显示Navigation的内容区。 说明&#xff1a; 该组件从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 该组件从API Version 11开始默认支持安全区避让特性(默认值为&#xff1a;expandSaf…

嘿!AI 编码新玩法上线!

随着 AI 智能浪潮到来&#xff0c;AI 编码助手成为越来越多开发者的必备工具&#xff0c;将开发者从繁重的编码工作中解放出来&#xff0c;极大地提高了编程效率&#xff0c;帮助开发者实现更快、更好的代码编写。 通义灵码正是这样一款基于阿里云通义代码大模型打造的智能编码…

Java学习笔记------拼图游戏

图形化界面GUI GUI&#xff1a;Graphical User Interface&#xff08;图像用户接口&#xff09;&#xff0c;指采用图形化的方式显示操作界面 两套体系&#xff1a;AWT包中和Swing包中 组件 JFrame&#xff1a;最外层的窗体 JMenuBar&#xff1a;最上层菜单 JLaber&#…

java继承,接口,抽象类

目录 目录 1 继承的含义 2 继承的好处 3使类与类之间产生了关系。 看这里继承-------我的理解 代码部分 接口 代码 抽象类 代码 各位友友们大家好呀&#x1f60a;&#xff01; 今天让我们继续回顾java&#xff0c;看看java中的抽象类以及接口继承是什么&#x1f914…

如何精确计算 π ?

如何精确计算 π &#xff1f; 01 原本是要回顾一下第六章内容&#xff0c;也就是“间隔性重复”。但我已经迫不及待&#xff0c;想要知道如何精确计算 π &#xff0c;因此&#xff0c;我们快走一步&#xff0c;来探讨一下 π 的计算。 对于 π 的计算&#xff0c;我从学校时…

浪潮信息数据中心管理平台InManage升级发布 新增三大场景功能

在AIGC应用日益广泛的当下&#xff0c;浪潮信息聚焦AIGC在数据中心运维管理中面临的难题&#xff0c;进一步通过技术创新升级功能及体验&#xff0c;为AIGC的高效应用创造了良好的基础。近日&#xff0c;浪潮信息数据中心管理平台InManage升级发布&#xff0c;新增资产数字化管…

智慧城市的未来:利用数字孪生技术推动智慧城市的智能化升级

目录 一、引言 二、数字孪生技术概述 三、数字孪生技术在智慧城市中的应用 1、城市规划与建设 2、城市管理与运营 3、公共服务与民生改善 4、应急管理与灾害防控 四、数字孪生技术推动智慧城市的智能化升级的价值 1、提高城市管理的智能化水平 2、优化城市资源配置 …

答题pk小程序源码技术大解析

答题pk小程序源码解析 在数字化时代&#xff0c;小程序因其便捷性、即用性而受到广泛欢迎。其中&#xff0c;答题pk小程序更是成为了一种寓教于乐的现象。它不仅为用户提供了趣味性的知识竞技平台&#xff0c;还为企业、教育机构等提供了互动营销和知识传播的新途径。本文将对…

2024年品牌推广:构建品牌生态圈与注重品牌故事和文化传播

在全球经济深度融合、数字化浪潮汹涌澎湃的2024年&#xff0c;品牌推广的策略与模式正经历着前所未有的变革。在这一背景下&#xff0c;构建品牌生态圈和注重品牌故事与文化传播&#xff0c;成为了企业提升品牌竞争力和市场占有率的重要手段。 一、2024年市场经济分析与现状 …

遥感与ChatGPT:科研中的强强联合

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已逐渐渗透到各个领域&#xff0c;为传统行业带来了前所未有的变革。其中&#xff0c;遥感技术作为观测和解析地球的重要手段&#xff0c;正逐渐与AI技术相结合&#xff0c;为地球科学研究与应用提供了全新的…

【elasticsearch】ES的JAVA工具类完整版(待完成...)

springboot 的 elasticsearch 版本: 7.15.2 前情提要: 1.首先要理解 elasticsearch 对于【数据类型】很严格,如果字段类型不规范,在 检索/排序/聚合 时候类型不正确就会出现报错或者查不到数据的问题。所以在一般String类型插入结构如下: 这样的结构,不仅可以支持分词查…

基于SpringBoot的招聘网站

基于jspmysqlSpring的SpringBoot招聘网站项目&#xff08;完整源码sql&#xff09; 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》…