算法题解记录10+++缺失的第一个正数

题目描述:

        给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

        请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:

输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:

输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。

示例 3:

输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。

提示:

  • 1 <= nums.length <= 105
  • -2^31 <= nums[i] <= 2^31 - 1

解题准备:

        1.了解基本操作:既然是找到缺失的第一个正数,必然涉及遍历(查找),其它的暂时看不出来。

        2.模拟操作:

        随便提供可能的数据,并得到它们的答案,如下图。

        人眼很快能得到结果,目前看不出步骤。

图1

解题难点1分析:

        难点1:看不出步骤。

        既然我们的目标是找到缺失的第一个正数,那么朴素的思想是:

        方案1:

        定义变量x=1,对数组元素每次遍历,完成遍历后x++,只要存在x不在数组中,那么它就是答案。

        对于【1,2,3……n】这样的数据,最多遍历n*n次即可,所以时间复杂度较高约为O(n^2)

        方案2:

        如果说遍历的效率比较低,我们可以自然地想到利用Hash表,采取空间换时间的思路,来优化算法。

        简单地说,遍历一次数组,把数组的元素全部添加进Hash集合HashSet中,然后利用其方法查找缺失的正数。

        查找的思路和方案1类似,都是定义变量x=1,一遍遍查找,只要x不在集合中,就是答案。

        不过明显地,且不说遍历一次数组,和遍历一次x,一共出现了两次,时间复杂度在O(n^2)

        就单单说使用Hash集合,已经开辟了O(n)的空间复杂度,所以还是有问题。

        当然,效率自然高了很多,只是不符合题意罢了。

解题难点2分析:

        难点2:如何优化算法,保证其效率的同时,又保证其空间复杂度不过高?

        无所谓,先把题目解决了再说,即使时间空间复杂度差一些。

        其实很多人也能想到,既然我们的目标是找到缺失的、最小的正数,那么:

        问题1:如果这个数组有序,不就很好解决了吗?

        比如,对于有序数组【-2,-1,0,1,2,3,4,5,……n】,遍历一遍数组,然后找到不相连的两个数,中间的数不就是答案吗?(当然,0到第一个正数、一直连续到最后一个数、仅一个数的数组、第一个数就比1大等等特殊情况,都值得注意)

        但是这确实是一个思路。

        解决方案也很简单:首先排序一遍【排序的时间复杂度可能很高,但一般不增加空间复杂度】,随后采用遍历方法,找到第一个非0的正数D(如果没有,返回1),判断一下D和1的关系(如果大于1,返回1),随后进入循环,

        判断一下D和下一个数N的关系(如果D+1!=N,说明二者不相连,那么D+1就是答案),如果相连,那么D进一步,直到把整个数组遍历完成。

        这个算法的时间复杂度大约在O(NlogN)左右,由于在原数组基础上排序,所以空间复杂度为O(1),复杂例子可能过不去,但是也是一种思路。

排序代码:

class Solution {public int firstMissingPositive(int[] nums) {Arrays.sort(nums); // 排序int L=0, R=0; // 双指针有助于遍历while(R<nums.length && nums[R]<=0 ){R++;}L=R;  // 指向第一个正数if(R>=nums.length){return 1; // 可能没有正数,如【-2,-1】}if(L==0){if(nums[L]!=1){return 1; // 可能第一个数就比1大,如【7,8,9】}}else if(nums[L-1]<=0 && nums[L]>1){return 1; // 可能既有负数,但是第一个正数就比1大,如【-2,-1,5,6】}if(R<nums.length-1){R++; // 保证之后的操作数组不越界}while(L<nums.length){if(nums[L]==nums[R]||nums[L]+1==nums[R]){ // 判断前后是否相连,相连有相同、+1相等两种形式,如【1,1】,【1,2】L++;if(R<nums.length-1){R++;}}else{return nums[L]+1; // 不相连,返回首个正数}}return nums[L-1]+1; // 遍历结束,全部相连,返回正数}
}

解题难点3分析:        

        本题我也是看了答案,如果让我做,我并不能以题目要求做出来,不过提供给我一种新思路:

        本题特殊思路:

        一个算法,其本质是提供一条路线,使输入转变为输出,如果从输入无法解决,不妨从结果集找思路。

        思考“解题难点1分析”中的“方案1”,可以发现这种穷举是最本质的做法,其它的行为都是在其上做优化。

        从结果集入手,可以发现,对于一个长度为n的数组,其缺失的正数只有n+1种可能,分别是从1到n+1。(如果是连续的,即为n+1,如【1,2,3】,该例答案为4)。

        1.那么,我们干脆定义一个辅助数组flag,其大小为n

        2.然后遍历输入数组nums,如果nums【i】满足,>0并且<=n(因为如果>n,它一定不是缺失的最小正数),,就使flag【nums[i]-1】=true;

        3.在遍历结束后,再遍历flag,只要flag【i】==false,就说明数组nums中没有这个正数,这就是答案。

        代码:
class Solution {public int firstMissingPositive(int[] nums) {boolean[] data=new boolean[nums.length];// 不初始化的原因,是JVM自动把boolean类型的数据置为false。for(int i=0; i<nums.length; i++){if(nums[i]<=nums.length&&nums[i]>0){ // 满足两个条件data[nums[i]-1]=true;}}for(int i=0; i<nums.length; i++){if(!data[i]){return i+1; // 返回答案}}// 如果全都是true,说明答案是n+1return nums.length+1;}
}

真正的答案:

        其实该题要求辅助空间为常数级别,所以解题难点3分析中的答案,也不符合题意,不过已经非常接近了。

        由于题目不限制修改数组nums,所以可以在数组nums的角度上操作,其原理和难点3类似,不过思路又更加特别。

        1.难点3中flag的作用就是映射,将答案映射到第一个false对应的下标上。

        2.其实采用一个全为0、大小为n的数组,同样满足该目的。

        3.不如使其映射到nums上。

        难点4:怎么做到呢?nums中既有正数、又有负数。

        步骤:

        1.负数不影响结果,不妨映射到n+1上(或者0,随你),也就是:遍历nums,如果nums【i】<=0,使nums【i】=n+1或者0。

        2.再一次遍历,正数如果满足nums【i】<=n,那么使nums【nums[i]-1】=0(等于0最好判断)【错误

        问题2:如果nums【i】-1比i更大(比如8和1),那么遍历到i=nums【i】-1即8时,这个数已经被置0了,那怎么处理?

        所以,原数据不能乱变,起码要使得后来的操作可以处理。

        3.删除2,同样的思路,使nums【nums[i]-1】= nums【nums[i]-1】,这保证了可以通过绝对值,获得数据。(这也是最难的一步)

        4.最后遍历一遍数组,和遍历boolean数组一样,找到第一个非负(boolean中是false)的数,这个数下标+1就是答案。

        5.如果全都小于等于0,说明答案是n+1。

代码不在此发布,因为不是我写的。

以上内容即我想分享的关于力扣热题10的一些知识。

        我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。

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

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

相关文章

Spring与Spring Boot的区别:从框架设计到应用开发

这是我自己开发的一款小程序&#xff0c;感兴趣的可以体验一下&#xff1a; 进入正题&#xff1a; 在Java开发领域&#xff0c;Spring和Spring Boot都是备受推崇的框架&#xff0c;它们为开发人员提供了丰富的功能和便捷的开发体验。然而&#xff0c;许多人对它们之间的区别仍…

MySQL的基础操作(二)

目录 一.数据库约束 1.主键约束 (Primary Key) 2.唯一约束 (Unique) 3.外键约束 (Foreign Key): 4.检查约束(Check) 5.默认约束 (Default) 二.聚合查询 1.简单聚合函数 2.GROUP BY子句 3.HAVING子句 三.联合查询 1.内连接 2.左连接 3.右连接 4.子查询 5.合并查询…

大数据实训进行时:数据标注项目

数据标注项目 培训目的 让同学们先熟悉理论知识&#xff0c;如&#xff1a;识别障碍物是否满足拉框的要求&#xff0c;如何进行拉框&#xff1b;熟悉标注操作&#xff0c;培养出能够进入正式项目的人员 培训地点 理论&#xff1a;学术报告厅、阶梯教室 实操&#xff1a;1实…

基于linux进一步理解核间通讯

芯片架构分为同构和异构: 如下图TC397: 如下图TDA4: 如下图STM32MP157: 非对称多处理结构(AMP): AMP 结构是指每个内核运行自己的 OS 或同一 OS 的独立实例&#

Day53 动态规划 part14

Day53 动态规划 part14 1143.最长公共子序列 我的思路&#xff1a; 模仿昨天的最大重复子序列长度的思路&#xff0c;可以列出如下状态转移方程 对着状态转移方程写代码即可&#xff0c;还是需要注意&#xff0c;i, j是从1开始的&#xff0c;比较的时候是str1[i -1]和str2[j…

【PG-1】PostgreSQL体系结构概述

1. PostgreSQL体系结构概述 代码结构 其中&#xff0c;backend是后端核心代码&#xff0c;包括右边的几个dir: access&#xff1a;处理数据访问方法和索引的代码。 bootstrap&#xff1a;数据库初始化相关的代码。 catalog&#xff1a;系统目录&#xff08;如表和索引的元数据…

2024年第十四届MathorCup数学应用挑战赛B题解题思路

B题https://mbd.pub/o/bread/ZZ6Wm5dx 问题1:对于附件I(Pre_test文件夹)给定的三张甲骨文原始拓片图 片进行图像预处理&#xff0c;提取图像特征&#xff0c;建立甲骨文图像预处理模型&#xff0c;实现对 甲骨文图像干扰元素的初步判别和处理。 针对问题1&#xff0c;对于附件…

【研发效能·创享大会-嗨享技术轰趴】-IDCF五周年专场

一、这是一场创新分享局&#xff01; 来吧&#xff0c;朋友们! 参加一场包含AIGC、BizDevOps、ToB产品管理、B端产品运营、平台工程、研发效能、研发度量、职业画布、DevOps国标解读的研发效能创享大会&#xff0c;会有哪些收益呢&#xff1f; 知识更新与技能提升&#xff1a;…

在线批量生成URL HTML单页网页程序

输入前缀、开始数字、结束数字、后缀 即可快速生成 几万、十万、百万 条链接。 支持 一键复制、 一键导出本地 txt 文件。 源码免费下载地址抄笔记 (chaobiji.cn)

CSS3 常用样式

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍CSS3 常用样式&#x1f48e;1 CSS3 新增选择器&#x1f339;1.1 属性选择器…

R语言 多组堆砌图

目录 数据格式 普通绘图 添加比例 R语言 堆砌图_r语言堆砌图-CSDN博客 关键点在于数据转换步骤和数据比例计算步骤&#xff0c;然后个性化调整图。 ①data <- melt(dat, id.vars c("ID"))##根据分组变为长数据 ②#计算百分比## data2 <- ddply(data, …

Ollama、FastGPT大模型RAG结合使用案例

参考: https://ollama.com/download/linux https://doc.fastai.site/docs/intro/ https://blog.csdn.net/m0_71142057/article/details/136738997 https://doc.fastgpt.run/docs/development/custom-models/m3e/ Ollama作为后端大模型加载运行 FastGPT作为前端页面聊天集成RA…

Redis中的集群(八)

集群 设置从节点 向一个节点发送命令: CLUSTER REPLICATE <node_id>可以让接收命令的节点成为node_id所指定节点的从节点&#xff0c;并开始对主节点进行复制: 1.接收到该命令的节点会首先会在自己的clusterState.nodes字典中找到node_id所对应节点的clusterNode结构,…

根据后端获取到的文档流,下载打开显示“无法打开文件”

原代码&#xff1a; download(item) {this.axios.get(api.download/item.name).then(res > {// console.log(res)let bob new Blob([res.data],{type: application/vnd.ms-excel})const link document.createElement(a);let url window.URL.createObjectURL(bob);link.d…

flutter中鼠标检测事件的应用---主要在于网页端使用

flutter中鼠标检测事件的应用—主要在于网页端使用 鼠标放上去 主要代码 import package:flutter/material.dart;class CustomStack extends StatefulWidget {override_CustomStack createState() > _CustomStack(); }class _CustomStack extends State<CustomStack>…

高质量ChatGPT Prompts 精选

通用超级 Prompt GPT4实用。通用超级 prompt &#xff0c;根据你想要的输出和你的反馈&#xff0c;自动使用相应的专家角色帮你解决问题。如果需要升级ChatGPT Plus&#xff0c;可以参考教程 升级 GPT4.0 保姆教程 您是一位具有多领域专长的专家级ChatGPT提示工程师。在我们…

YOLO算法改进Backbone系列之:Fcaformer

目前&#xff0c;设计更高效视觉Transformer的一个主要研究方向是通过采用稀疏注意力或使用局部注意力窗口来降低自我注意力模块的计算成本。相比之下&#xff0c;我们提出了一种不同的方法&#xff0c;旨在通过密集注意力模式来提高基于变换器的架构的性能。具体来说&#xff…

Fastjson报autotype is not support

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 打开AutoType功能 …

FANUC机器人通过ROBOGUIDE实现与实际的机器人进行程序导入导出的具体方法示例

FANUC机器人通过ROBOGUIDE实现与实际的机器人进行程序导入导出的具体方法示例 如下图所示,在电脑的开始菜单中找到”Robot Neiborhood”,点击进入, 如下图所示,设置要连接的机器人名称和主机IP地址(要确保自己的电脑和机器人IP地址在同一网段内),点击Add添加, 添加在线…

接招吧! selenium环境+元素定位大法

selenium 与 webdriver Selenium 是一个用于 Web 测试的工具&#xff0c;测试运行在浏览器中&#xff0c;就像真正的用户在手工操作一样。支持所有主流浏览器 WebDriver 就是对浏览器提供的原生API进行封装&#xff0c;使其成为一套更加面向对象的Selenium WebDriver API。 …