代码随想录算法训练营第五十九天 | 503. 下一个更大元素 II、42. 接雨水

news2024/11/27 12:41:36

503. 下一个更大元素 II

方法一:将两个nums数组放在一起,使用单调栈求下一个更大元素,最后再把结果集即result数组resize到原数组大小就可以了。

方法二:在遍历的过程中模拟走了两遍nums

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> res(nums.size(), -1);
        if (nums.size() == 0) return res;
        stack<int> st;
        st.push(0);
        for (int i = 1; i < nums.size() * 2; i++) {
            //因为是模拟两遍nums数组,所以真正的i要对nums.size()取余
            if (nums[i % nums.size()] < nums[st.top()]) st.push(i % nums.size());
            else if (nums[i % nums.size()] == nums[st.top()]) st.push(i % nums.size());
            else {
                while (!st.empty() && nums[i % nums.size()] > nums[st.top()]) {
                    res[st.top()] = nums[i % nums.size()];
                    st.pop();
                }
                st.push(i % nums.size());
            }
        }
        return res;
    }
};

42. 接雨水

暴力解法

按照列来计算如图:

如果按照列来计算的话,宽度一定是1了,同时再把每一列的雨水的高度求出来就可以了。

可以看出每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。

 首先从头遍历所有的列,并且要注意第一个柱子和最后一个柱子不接雨水

因为每次遍历列的时候,还要向两边寻找最高的列,所以时间复杂度为O(n^2),空间复杂度为O(1)

但暴力解法超时

双指针

通过暴力解法可以看出只要记录左边柱子的最高高度 和 右边柱子的最高高度,就可以计算当前位置的雨水面积,这就是通过列来计算。

当前列雨水面积:min(左边柱子的最高高度,记录右边柱子的最高高度) - 当前柱子高度。

为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍,这其实是有重复计算的。

把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight),这样就避免了重复计算。

当前位置,左边的最高高度是前一个位置的左边最高高度和本高度的最大值。

即从左向右遍历:maxLeft[i] = max(height[i], maxLeft[i - 1]);

从右向左遍历:maxRight[i] = max(height[i], maxRight[i + 1]);

单调栈

1、单调栈是按照行方向来计算雨水,如图:

2、使用单调栈内元素的顺序

 

从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。

因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。

如图:

3、遇到相同高度的柱子怎么办

遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。

例如 5 5 1 3 这种情况。如果添加第二个5的时候就应该将第一个5的下标弹出,把第二个5添加到栈中。

因为我们要求宽度的时候 如果遇到相同高度的柱子,需要使用最右边的柱子来计算宽度

如图所示:

4、栈里要保存什么数值 

使用单调栈,也是通过 长 * 宽 来计算雨水面积的。

长就是通过柱子的高度来计算,宽是通过柱子之间的下标来计算,

那么栈里有没有必要存一个pair<int, int>类型的元素,保存柱子的高度和下标呢。

其实不用,栈里就存放下标就行,想要知道对应的高度,通过height[stack.top()] 就知道弹出的下标对应的高度了。

所以栈的定义如下:

stack<int> st; // 存着下标,计算的时候用下标对应的柱子高度

以下逻辑主要就是三种情况

  • 情况一:当前遍历的元素(柱子)高度小于栈顶元素的高度 height[i] < height[st.top()]
  • 情况二:当前遍历的元素(柱子)高度等于栈顶元素的高度 height[i] == height[st.top()]
  • 情况三:当前遍历的元素(柱子)高度大于栈顶元素的高度 height[i] > height[st.top()]

先将下标0的柱子加入到栈中,st.push(0);。 栈中存放我们遍历过的元素,所以先将下标0加进来。

然后开始从下标1开始遍历所有的柱子,for (int i = 1; i < height.size(); i++)

如果当前遍历的元素(柱子)高度小于栈顶元素的高度,就把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序(从栈头到栈底)。

如果当前遍历的元素(柱子)高度等于栈顶元素的高度,要跟更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度。

如果当前遍历的元素(柱子)高度大于栈顶元素的高度,此时就出现凹槽了,如图所示:

取栈顶元素,将栈顶元素弹出,这个就是凹槽的底部,也就是中间位置,下标记为mid,对应的高度为height[mid](就是图中的高度1)。

此时的栈顶元素st.top(),就是凹槽的左边位置,下标为st.top(),对应的高度为height[st.top()](就是图中的高度2)。

当前遍历的元素i,就是凹槽右边的位置,下标为i,对应的高度为height[i](就是图中的高度3)。

此时可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的元素,三个元素来接水!

那么雨水高度是 min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度,代码为:int h = min(height[st.top()], height[i]) - height[mid];

雨水的宽度是 凹槽右边的下标 - 凹槽左边的下标 - 1(因为只求中间宽度),代码为:int w = i - st.top() - 1 ;

当前凹槽雨水的体积就是:h * w

 

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> st; //存下标,计算柱子高度
        st.push(0);
        int sum = 0;
        for (int i = 1; i < height.size(); i++) {
            if (height[i] < height[st.top()]) {
                st.push(i);
            } else if (height[i] == height[st.top()]) {
                st.push(i);
            } else {
                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;
    }
};

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

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

相关文章

5G-OAI关于物理层中PDCCH源码解析

5G物理层是指5G网络的传输技术&#xff0c;包括无线帧、子帧、时隙、符号等方面的定义和规范。具体来说&#xff0c;5G物理层定义了无线帧的长度、帧结构、子帧结构、传输速率、带宽、时间同步等方面的参数&#xff0c;以及物理层信道的编码、调制和解调方式等方面的规范。5G物…

k8s 滚动部署学习总结

k8s 滚动部署学习总结 滚动发布 滚动发布配置总结 定义&#xff1a; 滚动升级&#xff08;Rolling update&#xff09; 就是指每次更新部分Pod&#xff0c;而不是在同一时刻将该Service下面的所有Pod shutdown&#xff0c;然后去更新逐个更新可以避免将业务中断 使用Deploy…

GEE初学者笔记之快速上手篇

1.基础概念 (1)谷歌云平台 整个GEE是基于Google Cloud云平台的一整套API开发环境。因此整个数据的处理全部都是在Google Cloud平台上实现的&#xff0c;无需本地机器参与运算。一般开发流程是在线/离线编辑代码&#xff0c;然后提交服务器端运行&#xff0c;完成之后会输出给我…

【Jenkins 2.x 实践指南】1.4 软件工程生产力--章节小结

目录 一、生产力三要素 1. 生产力 2. IT 中的生产力 二、Devops 和 Jenkins 1. DevOps 模式定义(AWS官方定义) 2. DevOps 实践经验 2.1 持续集成 2.2 持续交付 2.3 微服务 2.4 基础设施即代码 2.5 监控和日志记录 2.6 沟通与合作 一、生产力三要素 1. 生产力 劳动…

GPT系列简介与gpt训练(nanoGPT)

generateivelt pre-trained transformer ,GPT使用transformer做特征提取行&#xff0c;单项语言模型作为训练任务 gpt 1.0 通过自左向右生成式的构建预训练任务&#xff0c;然后得到一个通用的预训练模型&#xff0c;这个模型和BERT一样都可用来做下游任务的微调。GPT-1当时在…

Firefly-rk3288 开发板Linux系统编译

前言 手上的一块Firefly-RK3288开发板&#xff0c;看了下Firefly提供的SDK&#xff0c;压缩包就有15个多G&#xff0c;直接吓退。还好最近看到了韦东山老师提供的教学资料。记下学习步骤及遇到的问题解决办法。 1、开发环境 资料提供的有百问网制作的 ubuntu18.04 虚拟机镜像…

卷积计算转换为矩阵乘计算的几种场景和方法

本文默认卷积的输入输出数据格式为NHWC。 1x1卷积 输入shape为[N, H, W, C] , filter为[Hf, Wf, Ci, Co] FH, FW都为1&#xff0c;直接把输入shape reshape为[N, H * W, C], filter reshape为[[Hf * Wf * Ci, Co],然后进行矩阵乘得到[N, H * W, Co]&#xff0c;再reshape为卷…

ChatGPT 本地部署及搭建

这篇简要说下清华开源项目 ChatGLM 本地部署的详细教程。清华开源项目 ChatGLM-6B 已发布开源版本&#xff0c;这一项目可以直接部署在本地计算机上做测试&#xff0c;无需联网即可体验与 AI 聊天的乐趣。 项目地址&#xff1a;GitHub - THUDM/ChatGLM-6B: ChatGLM-6B&#xf…

一次小破站JS代码审计出XSS漏洞思路学习

今天看了小破站一个大佬的分析&#xff0c;感觉思路很有意思&#xff0c;感兴趣的xdm可以到大佬视频下提供的链接进行测试&#xff08;传送门&#xff09;这类社交平台的XSS漏洞利用起来其实危害是特别大的&#xff0c;利用XSS能在社交平台上呈现蠕虫式的扩散&#xff0c;大部分…

redis内存回收——过期、淘汰

DB结构删除策略惰性删除周期删除SLOWFAST淘汰策略redis内存设置过大时会增加同步等操作的复杂度 DB结构 /* Redis database representation. There are multiple databases identified* by integers from 0 (the default database) up to the max configured* database. The …

es 搜索中同时包含 “query“ 和 “filter“ 子句

Elasticsearch支持很多查询方式&#xff0c;其中一种就是DSL&#xff0c;它是把请求写在JSON里面&#xff0c;然后进行相关的查询。 一、Query DSL 与 Filter DSL DSL查询语言中存在两种&#xff1a;查询DSL&#xff08;query DSL&#xff09;和过滤DSL&#xff08;filter DSL…

数据库管理-第六十八期 Oracle 23c的其他(20230417)

数据库管理 2023-04-17第六十八期 Oracle 23c的其他1 DGPDB2 无锁并发总结第六十八期 Oracle 23c的其他 由于Oracle 23c的文档相对较少&#xff0c;一是当前文档主要面向开发人员&#xff0c;二是感觉实际内容还在不断增加&#xff0c;主要还有一点就是各种新特性的在官方文档…

几分种学会React Router v6使用

React路由可以实现页面间的切换。 传送门&#xff1a;英文文档 中文教程&#xff1a; https://www.reactrouter.cn/docs/getting-started/tutorial 1.基础使用 react 需求&#xff1a;实现一个普通的底部导航切换 1.安装react-router npm i react-router-dom62.配置根组件…

C#调试与测试 | DebuggerDisplay使用技巧

DebuggerDisplay使用技巧 文章目录DebuggerDisplay使用技巧前言DebuggerDisplay介绍示例代码前言 当你在开发一个大型的应用程序时&#xff0c;调试是一个不可避免的任务。调试器是你的好朋友&#xff0c;但是有时候它并不能直接给你所需的信息。这时&#xff0c;就需要使用 C…

线上问题排查异闻录

如何解决堆内存溢出问题 OOM有很多种情况啊&#xff0c;这里就先讲解最常见也是最容易观测的java.lang.OutOfMemoryError: Java heap space&#xff0c;也就是堆内存溢出。 发现 启动Java程序的时候&#xff0c;最好参数加上-XX:HeapDumpOnOutOfMemoryError&#xff0c;该参…

【RabbitMQ】RabbitMQ控制台的使用

一、访问控制台页面 如果在本机上装了RabbitMQ则在浏览器访问127.0.0.1:15672,如果在服务器装了RabbitMQ则通过在浏览器输入urlip:15762来访问 登录后进入主页 二、添加RabbitMQ用户 进入主页后选择Admin&#xff0c;对应找到添加用户选择输入信息后即可完成添加 三、添加Rab…

GROUP BY 与 聚合函数、 HAVING 与 ORDER BY-MySQL数据库 - 分组选择数据(头歌实践教学平台)

文章目的初衷是希望学习笔记分享给更多的伙伴&#xff0c;并无盈利目的&#xff0c;尊重版权&#xff0c;如有侵犯&#xff0c;请官方工作人员联系博主谢谢。 目录 第1关&#xff1a;GROUP BY 与 聚合函数 任务描述 相关知识 GROUP BY与聚合函数的使用 编程要求 第2关&…

交通 | 应用Benders分解方法解决多车生产路由问题

论文解读​ 曲晨辉&#xff0c;王飞龙 1 知识补充和文章贡献 2.1 IRP (Inventory routing problems) IRP关注的是在一个给定的规划范围内&#xff0c;从一个设施到一组客户的单一产品分配。客户以给定的速度消费产品&#xff0c;并可将产品的库存维持在一个特定的水平上。一组…

HTB-SolidState

HTB-SolidState信息收集80端口Apache Jamesmindyrbash绕过mindy -> root总结信息收集 80端口 目录扫描 从/README.txt文件里知道他们在捣鼓一个新的秘密项目&#xff0c;这个新的秘密项目就是一个新的网页外观。 80端口先点到为止&#xff0c;免得进兔子洞。 Apache James …

基于SpringBoot技术点餐系统的设计与实现(论文+源码)_kaic

摘 要 饮食行业的发展推动了服务的提升&#xff0c;在线点餐服务模式随之产生。相比于传统点餐&#xff0c;在线点餐更加方便地浏览菜品&#xff0c;挑选菜品&#xff0c;有更好的用餐体验。系统的使用减少了人工成本&#xff0c;方便数据统计&#xff0c;便于提供更优质的服务…