代码随想录算法训练营day59|第十章 单调栈part02

2024-03-14 04:36

本文主要是介绍代码随想录算法训练营day59|第十章 单调栈part02,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

503.下一个更大元素II 

42. 接雨水  


 

503.下一个更大元素II 

这道题和 739. 每日温度 几乎如出一辙,可以自己尝试做一做

 

代码随想录

这道题可以直接拼接数组,但是显然使用取余运算更划算。注意这回 i 代表的不直接是nums的下标,而更多的是遍历次数,取余之后才会是nums下标。还有文章里面给出的for的循环次数是nums.size()*2-1,而实际上可以是nums.size()*2-2,因为之所以要遍历两遍nums,是为了让所有的元素找临近较大值的时候可以从它的左边转一圈找到它的右边,所以针对最后后一个元素的寻找(其他元素早就满足这种寻找了),可以不遍历最后一个元素本身。

vector<int> nextGreaterElements(vector<int>& nums) {stack<int> st;vector<int> res(nums.size(),-1);st.push(0);for(int i=1;i<nums.size()*2-1;i++){while(st.size()&&nums[i%nums.size()]>nums[st.top()]){res[st.top()]=nums[i%nums.size()];st.pop();}st.push(i%nums.size());}return res;}

42. 接雨水  

接雨水这道题目是 面试中特别高频的一道题,也是单调栈 应用的题目,大家好好做做。建议是掌握 双指针 和单调栈,因为在面试中 写出单调栈可能 有点难度,但双指针思路更直接一些。在时间紧张的情况有,能写出双指针法也是不错的,然后可以和面试官在慢慢讨论如何优化。 

代码随想录

这道题使用双指针的思路其实是遍历两遍height数组,分别找到它的右边最高的柱子和左边最高的柱子,然后取这两个的最小值,这个值就是填满水之后应该达到的高度,如果这个高度是正值那就加上,反之说明不合法则不予理会,以此来求当前下标处增加的水量。

遍历求右边最高柱子的时候要从右往左遍历,如果当前的柱子高度小于历史最高柱子的高度,那就把历史最高柱子高度赋值给它,反之如果大于,那就证明当前柱子的右边没有比它更高的柱子了,于是这个下标处也不会盛水,所以为了依旧套用递推公式,这个地方应该赋值为当前柱子的高度(在使用递推公式推导的时候,需要求最小值,这个最小值有可能是当前柱子的高度,那么计算出来值就会是0,而如果是最左边柱子的高度,那么这个值就会是负数,而因为不合法,所以不被加入)。于是推导公式就简化为取当前柱子高度和历史柱子最高高度的最大值。求左边最高柱子数组差不多一个道理,只是需要倒序遍历。注意,可以事先设置这个最大高度为0,然后遍历就可以从两端开始,或者也可以直接把两端的值设置为两端柱子的高度,这样可以少遍历一个值,其实大差不差。

b5f475ca069b4318ac336879f69547c6.png

int trap(vector<int>& height) {if (height.size() <= 2) return 0;vector<int> maxLeft(height.size(), 0);vector<int> maxRight(height.size(), 0);int size = maxRight.size();// 记录每个柱子左边柱子最大高度maxLeft[0] = height[0];for (int i = 1; i < size; i++) {maxLeft[i] = max(height[i], maxLeft[i - 1]);}// 记录每个柱子右边柱子最大高度maxRight[size - 1] = height[size - 1];for (int i = size - 2; i >= 0; i--) {maxRight[i] = max(height[i], maxRight[i + 1]);}// 求和int sum = 0;for (int i = 0; i < size; i++) {int count = min(maxLeft[i], maxRight[i]) - height[i];if (count > 0) sum += count;}return sum;}

这道题使用单调栈做法也比较复杂,因为单调栈每次会弹出一些元素,所以不能像双指针做法那样按列来求,而是要一行一行的求,也就是除了求增加水量的高度之外,还要求增加水量的宽度(上一题直接求高度代表水量是因为宽度默认为1了)。

每次如果遍历到大于栈顶元素的值,那就先记录一下当前的栈顶元素,然后再弹出这个栈顶元素,然后再判断一下这个栈里面是否还剩有元素,如果剩有元素,证明可能构成一个凹槽用来盛水,那就要计算盛水的水量,先计算水的高度,水的高度取遍历的柱子的高度和栈顶高度的最小值再减去之前储存的那个栈顶元素,水的宽度当然就是遍历的元素的下标和现在栈顶元素的下标的下标差再减一(因为求的是中间的部分,用来盛水的那种宽度),相乘求得水量;而如果没有元素剩余,那就证明不能盛水。无论能否盛水,都需要将当前元素压入栈,以便后来的判断。如果遍历到小于等于栈顶元素的值,那就直接压入栈。

其实便利到等于栈顶元素的值有两种处理方法,第一种方法是直接压入栈中,然后按上面的做法来处理;另一种做法是舍弃掉这个元素,其实就算不舍弃压入栈中,最后公式计算得到的增加水量也是零,所以没什么太大差别。

afe86d9a5d7e46df9c4a658a30758479.png

int trap(vector<int>& height) {stack<int> st;st.push(0);int sum = 0;for (int i = 1; i < height.size(); i++) {while (!st.empty() && height[i] > height[st.top()]) {int mid = st.top();st.pop();if (!st.empty()) {int h = min(height[st.top()], height[i]) - height[mid];int w = i - st.top() - 1;sum += h * w;}}st.push(i);}return sum;}

 

 

这篇关于代码随想录算法训练营day59|第十章 单调栈part02的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/807205

相关文章

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

Java集合之Iterator迭代器实现代码解析

《Java集合之Iterator迭代器实现代码解析》迭代器Iterator是Java集合框架中的一个核心接口,位于java.util包下,它定义了一种标准的元素访问机制,为各种集合类型提供了一种统一的... 目录一、什么是Iterator二、Iterator的核心方法三、基本使用示例四、Iterator的工

Java 线程池+分布式实现代码

《Java线程池+分布式实现代码》在Java开发中,池通过预先创建并管理一定数量的资源,避免频繁创建和销毁资源带来的性能开销,从而提高系统效率,:本文主要介绍Java线程池+分布式实现代码,需要... 目录1. 线程池1.1 自定义线程池实现1.1.1 线程池核心1.1.2 代码示例1.2 总结流程2. J

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

Vue实现路由守卫的示例代码

《Vue实现路由守卫的示例代码》Vue路由守卫是控制页面导航的钩子函数,主要用于鉴权、数据预加载等场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、概念二、类型三、实战一、概念路由守卫(Navigation Guards)本质上就是 在路

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型

Python屏幕抓取和录制的详细代码示例

《Python屏幕抓取和录制的详细代码示例》随着现代计算机性能的提高和网络速度的加快,越来越多的用户需要对他们的屏幕进行录制,:本文主要介绍Python屏幕抓取和录制的相关资料,需要的朋友可以参考... 目录一、常用 python 屏幕抓取库二、pyautogui 截屏示例三、mss 高性能截图四、Pill

使用MapStruct实现Java对象映射的示例代码

《使用MapStruct实现Java对象映射的示例代码》本文主要介绍了使用MapStruct实现Java对象映射的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、什么是 MapStruct?二、实战演练:三步集成 MapStruct第一步:添加 Mave