DAY56:单调栈(二)下一个最大元素Ⅱ(环形数组处理思路)
文章目录
- 思路
- 写法1完整版
- 环形数组处理:i取模,遍历两遍
- 写法2完整版(环形数组推荐写法)
- debug测试:
- 逻辑运算符短路特性
- result数组在栈口取元素,是否会覆盖原有数值?
给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。
数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。
示例 1:
输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
示例 2:
输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]
提示:
1 <= nums.length <= 10^4-10^9 <= nums[i] <= 10^9
思路
本题属于循环数组问题,循环数组的处理,我们可以将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小即可。
但这种写法,修改了nums数组,而且最后还要把result数组resize回去。resize倒是不费时间,是O(1)的操作,但扩充nums数组相当于**多了一个O(n)**的操作。时间复杂度和空间复杂度都多了O(n)。
写法1完整版
// 版本一
class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {// 拼接一个新的numsvector<int> nums1(nums.begin(), nums.end());nums.insert(nums.end(), nums1.begin(), nums1.end());// 用新的nums大小来初始化resultvector<int> result(nums.size(), -1);if (nums.size() == 0) return result;// 开始单调栈stack<int> st;st.push(0);for (int i = 1; i < nums.size(); i++) { if (nums[i] < nums[st.top()]) st.push(i); else if (nums[i] == nums[st.top()]) st.push(i);else { while (!st.empty() && nums[i] > nums[st.top()]) {result[st.top()] = nums[i];st.pop();}st.push(i);}}// 最后再把结果集即result数组resize到原数组大小result.resize(nums.size() / 2);return result;}
};
环形数组处理:i取模,遍历两遍
对于这种循环数组, nums[nums.length - 1] 的下一个元素是 nums[0] ,需要遍历两遍,可以通过给i取模来解决!
我们首先扩充for循环遍历范围,令for遍历范围为[0,nums.size()*2-1](这样就遍历了2n个位置,遍历长度为2n),然后nums[i]改为nums[i%nums.size()]。
由于取模运算的特性, i初始值=0,i%nums.size()这个式子就是0--nums.size()-1循环取值。
- 当i初始值=0时,i%a的范围就是[0,a-1]!
因为 “求模” 运算的定义是 “求余数”。例如,当 7 除以 3,结果是 2 余 1,所以 7%3 的结果是 1。余数总是会小于除数的,所以 i%a 的结果将始终在 0 到 a-1 的范围内。
当 i 小于 a 时,i%a 的结果就是 i 自己;当 i 等于 a 时,i%a 的结果就是 0;当 i 大于 a 时,i%a 的结果就是 i-a 的值,直到这个值小于 a 为止。
遍历两遍的逻辑:
st.push(0);
for(int i=1;i<nums.size()*2;i++){if(nums[i%nums.size()]<=nums[st.top()]){st.push(i%nums.size());}else{while(nums[i%nums.size()]>nums[st.top()]&&!st.empty()){result[st.top()]=nums[i%nums.size()];st.pop();}st.push(nums[i%nums.size()]);}
}
写法2完整版(环形数组推荐写法)
- 重点在只用O(n)的时间复杂度和空间复杂度,完成遍历两遍数组
class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {stack<int>st;vector<int>result(nums.size(),-1);st.push(0);for(int i=1;i<nums.size()*2;i++){if(nums[i%nums.size()]<=nums[st.top()]){st.push(i%nums.size());}else{while(!st.empty()&&nums[i%nums.size()]>nums[st.top()]){result[st.top()]=nums[i%nums.size()];st.pop();}st.push(i%nums.size());}}return result;}
};
debug测试:
Line 171: Char 16: runtime error: reference binding to misaligned address 0xbebebebebebec0ba for type ‘int’, which requires 4 byte alignment (stl_deque.h) 0xbebebebebebec0ba: note: pointer points here

错误信息的意思是:运行时发生了一种未定义行为(Undefined Behavior)。具体来说,它在尝试对一个非对齐的地址(即不是4字节对齐的地址)进行整数的引用绑定,而这个操作是未定义的。该错误通常发生在空指针解引用,数组越界等情况。
这个错误出现在while循环这一句:
while(nums[i%nums.size()]>nums[st.top()]&&!st.empty())
while 循环如果这么写,那么,在检查栈是否为空之前,就已经尝试从栈顶取值,这是有问题的。当栈为空时,这将会导致未定义行为。
逻辑运算符短路特性
在C++中,逻辑AND操作符(&&)和逻辑OR操作符(||)都具有"短路"特性。
对于逻辑AND操作符,如果左边的操作数为假,那么不论右边的操作数是什么,整个表达式的结果都是假,因此不需要再计算右边的操作数。对于逻辑OR操作符,如果左边的操作数为真,那么不论右边的操作数是什么,整个表达式的结果都是真,因此不需要再计算右边的操作数。
因此,写单调栈的while循环,while条件里面包括了非空检查的时候,检查栈是否为空的语句必须放在前面,确定非空之后再尝试从栈顶取值!如果栈已经为空,那么!st.empty()的结果为假,右边的nums[i%nums.size()] > nums[st.top()]就不会被执行,从而避免对空栈进行操作的未定义行为。
result数组在栈口取元素,是否会覆盖原有数值?
答案是不会,因为result更新,是在发现了一个更大的数值,弹出的时候才会更新。
例如4 3 2这个例子,遍历两遍得到的是4 3 2 4 3 2,实际上后面那一组4 3 2的下标还是0 1 2,数组下标是没有扩展的。
但是遍历前面这一组4 3 2的时候,因为单调递减,所以全部入栈,栈内为2 3 4,遍历第二遍的时候遇到了4,栈内的2 3才被弹出,相当于result[1]和[2]此时更新。但是到了后面,3 2继续入栈,到最后2 3 4都留在了栈里面不会被弹出,因此也不可能导致result的值被覆盖!
再例如2 3 4的例子,遍历两遍得到2 3 4 2 3 4,第一遍的时候result就已经被填满,result[0]=3,result[1]=4,result[2]=-1。到了遍历第二遍的时候,此时栈内只有4,第二次遍历时,2入栈之后3再入栈,会弹出2,相当于result[0]仍然=3,同理result[1]仍然=4。即使是result的值覆盖了,结果依旧是不变的。
相关文章:
DAY56:单调栈(二)下一个最大元素Ⅱ(环形数组处理思路)
文章目录 思路写法1完整版环形数组处理:i取模,遍历两遍写法2完整版(环形数组推荐写法)debug测试:逻辑运算符短路特性result数组在栈口取元素,是否会覆盖原有数值? 给定一个循环数组 nums &#…...
kafka简介
kafka是什么? Kafka最初采用Scala语言开发的一个多分区、多副本并且基于ZooKeeper协调的分布式消息系统。目前Kafka已经定位为一个分布式流式处理平台,它的特性有高吞吐、可持久化、可水平扩展、支持流处理。 Apache Kafka是一个分布式的发布-订阅消息系…...
Kafka-消费者组消费流程
消费者向kafka集群发送消费请求,消费者客户端默认每次从kafka集群拉取50M数据,放到缓冲队列中,消费者从缓冲队列中每次拉取500条数据进行消费。...
FFmepg视频解码
1 前言 上一篇文章<FFmpeg下载安装及Windows开发环境设置>介绍了FFmpeg的下载安装及环境配置,本文介绍最简单的FFmpeg视频解码示例。 2 视频解码过程 本文只讨论视频解码。 FFmpeg视频解码的过程比较简单,实际就4步: 打开媒体流获取…...
SpringCloud深入理解 | 生产者、消费者
💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! SpringCloud Spring Cloud是一组用于构建分布式系统和微服务架构的开源框架和工具集合。它是在Spring生态系统的基础上构建的,旨在简化开发人员构建分布式…...
web题型
0X01 命令执行 漏洞原理 没有对用户输入的内容进行一定过滤直接传给shell_exec、system一类函数执行 看一个具体例子 cmd1|cmd2:无论cmd1是否执行成功,cmd2将被执行 cmd1;cmd2:无论cmd1是否执行成功,cmd2将被执行 cmd1&cmd2:无论cmd1是否执行成…...
使用curl和postman调用Azure OpenAI Restful API
使用curl在cmd中调用时,注意:json大括号内的每一个双引号前需要加上\ curl https://xxxopenai.openai.azure.com/openai/deployments/Your_deployid/chat/completions?api-version2023-05-15 -H "Content-Type: application/json" -H "…...
草莓叶病害数据集
1.草莓数据集有两个文件夹 训练集 健康文件夹(2819张) 草莓叶焦病害(3327张) 数据集可以关注最后一行 import numpy as np import os import matplotlib.pyplot as plt import cv2import warnings warnings.filterwarnings(igno…...
安卓音视频多对多级联转发渲染
最近利用自己以前学习和用到的音视频知识和工程技能做了一个android的sdk,实现了本地流媒体ipc rtsp 拉流以及自带mip usb等camera audio节点产生的流媒体通过webrtc sfu的方式进行多对多级联发布共享,网状结构,p2p组网,支持实时渲染以及转推rtmp&#x…...
2023年电赛---运动目标控制与自动追踪系统(E题)OpenART mini的代码移植到OpenMV
前言 (1)已经有不少同学根据我上一篇博客完成了前三问,恭喜恭喜。有很多同学卡在了第四问。 (2)我说了OpenART mini的代码是可行的。但是他们不会移植到OpenMV上,再次我讲移植之后的代码贴出来。 ÿ…...
SAP CAP篇十二:AppRouter 深入研究
本文目录 本系列文章理解现有程序app文件夹中的package.json理解approuter.js 修改现有程序修改package.json新建index.js在Approuter中显示额外的逻辑 添加一些额外的Logger对应代码及branch 本系列文章 SAP CAP篇一: 快速创建一个Service,基于Java的实现 SAP CAP…...
HDFS中数据迁移的使用场景和考量因素
HDFS中数据迁移的使用场景和考量因素 数据迁移使用场景数据迁移要素考量HDFS分布式拷贝工具-DistCpdistcp的优势性能命令 数据迁移使用场景 冷热集群数据同步、分类存储集群数据整体搬迁 当公司业务迅速的发展,导致的当前的服务器数量资源出现临时紧张的时候&#…...
科普 | 以太坊坎昆升级是什么
坎昆升级是什么 坎昆,是墨西哥一个著名的旅游城市,也是 Devcon 3 大会的举办地,按照以太坊升级命名的规律,以地名命名的升级,是针对以太坊执行层的升级。 之前同样命名的还有柏林升级、伦敦升级和这次的上海升级等。…...
C# 一些知识整理
C#反射和特性 反射Reflection Type 类型 Name NameSpace Assembly GetFields() GetProperties() GetMethods() 特性Attribute Obsolete弃用 Condit…...
SpringBoot复习:(15)Spring容器的核心方法refresh是在哪里被调用的?
在SpringApplication的run方法: refreshContext代码如下: 其中调用的refresh方法代码如下: 其中调用的refresh方法代码如下: 其中调用的fresh方法代码如下: 其中调用了super.refresh();而这个super.refresh()就是…...
Android安卓实战项目(5)---完整的健身APP基于安卓(源码在文末)可用于比赛项目或者作业参考中
Android安卓实战项目(5)—完整的健身APP(源码在文末🐕🐕🐕)可用于比赛项目 一.项目运行介绍 1.大致浏览 【bilibili视频】 https://www.bilibili.com/video/BV1uX4y177iR/? (1&…...
AutoSAR系列讲解(实践篇)11.2-存储处理与Block
目录 一、NVRAM Block NVRAM Block的类型 二、Fee Block 三、Ea Block 四、总结 同通信的PDU一样,存储功能也需要一些特殊的数据结构来存放和管理我们的NV数据(NV data) 一、NVRAM Block NVRAM Block的作用类似于IPDU,但它们两仅仅只是作用上相似,其功能实现是完全…...
K8s总结
K8s 是什么 Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的机制…...
3.playbook剧本二
文章目录 playbook二Roles模块roles模式安装LNMP创建nginxfiles目录handlers目录tasks目录templates目录vars目录 创建mysqltasks目录 创建phpfiles目录handlers目录tasks目录templates目录vars目录 创建LNMP剧本文件 playbook二 Roles模块 角色的作用:把playbook…...
【MySQL】视图与用户管理
【MySQL】视图 视图视图概念使用基表与视图的相互影响 用户管理新增用户删除修改密码 用户权限授予权限回收权限 视图 视图概念 视图就是一张虚拟表,其内容由查询定义。与真实的表一样,视图包含一系列带有名称的列和行数据。视图的数据变化影响到基表&…...
PyTorch 2.8镜像效果实测:Wan2.2-I2V图生视频在4090D上的流畅度表现
PyTorch 2.8镜像效果实测:Wan2.2-I2V图生视频在4090D上的流畅度表现 1. 测试环境与配置 1.1 硬件配置 本次测试使用的是基于RTX 4090D显卡的深度学习工作站,具体配置如下: 显卡:NVIDIA RTX 4090D 24GB显存CPU:10核…...
告别重复造轮子:用快马AI一键生成嵌入式Modbus协议栈提升效率
作为一名嵌入式开发者,我经常需要为各种项目实现Modbus通信协议。每次从零开始编写协议栈不仅耗时,还容易引入低级错误。最近尝试用InsCode(快马)平台生成基础框架,效率提升明显,分享下具体实践过程。 传统开发痛点分析 在STM32项…...
2026 API 中转平台选型报告:从冗余性到工程效率
1. 4SAPI —— 商业生产的“压舱石”4SAPI 在 2026 年的技术站位极其稳固,主要得益于其对**企业级 SLA(服务等级协议)**的严苛执行。核心逻辑:其底层架构采用了类似多云 CDN 的分发机制。当上游官方接口(如 OpenAI 或 …...
APDS9960手势传感器驱动开发与嵌入式实战
1. APDS9960手势传感器库技术解析与嵌入式工程实践APDS9960是一款由Broadcom(原Avago)推出的集成环境光、颜色、接近度及手势识别功能的多模态光学传感器芯片。其核心价值在于将传统分立式光感方案(如独立ALSProximityGesture模块)…...
BilibiliDown:如何高效批量下载B站视频并实现离线收藏管理?
BilibiliDown:如何高效批量下载B站视频并实现离线收藏管理? 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.…...
Llama-3.2V-11B-cot快速部署:Docker镜像开箱即用,5分钟启动视觉CoT服务
Llama-3.2V-11B-cot快速部署:Docker镜像开箱即用,5分钟启动视觉CoT服务 1. 项目概述 Llama-3.2V-11B-cot是一个支持系统性推理的视觉语言模型,基于LLaVA-CoT论文实现。这个模型能够理解图像内容并进行逐步推理,最终给出合理的结…...
嵌入式系统中的累加和校验算法原理与实现
1. 累加和校验算法概述在嵌入式系统开发中,数据通信的可靠性至关重要。想象一下,当你通过无线模块控制一台工业机器人时,如果传输的运动指令数据出现错误,可能导致机械臂做出完全不可预测的动作,轻则损坏产品ÿ…...
终极指南:CleanArchitecture项目Angular 17快速升级实战与最佳实践
终极指南:CleanArchitecture项目Angular 17快速升级实战与最佳实践 【免费下载链接】CleanArchitecture Clean Architecture Solution Template for ASP.NET Core 项目地址: https://gitcode.com/GitHub_Trending/cle/CleanArchitecture 如果你正在使用Clean…...
解密网页资源批量下载:ResourcesSaverExt实战配置指南
解密网页资源批量下载:ResourcesSaverExt实战配置指南 【免费下载链接】ResourcesSaverExt Chrome Extension for one click downloading all resources files and keeping folder structures. 项目地址: https://gitcode.com/gh_mirrors/re/ResourcesSaverExt …...
3步搭建JNPF工作流:新手也能玩转全流程类型
接触过不少刚入门低代码的开发和企业数字化人员,一提搭建工作流就犯怵:分不清流程类型适配场景,摸不透决策流的规则配置,搞不定自由流的灵活流转,最后要么搭出的流程适配性差,要么冗余臃肿跑不通。 其实基于…...
