当前位置: 首页 > news >正文

力扣 41.缺少的第一个正整数

题目描述

给你一个未排序的整数数组 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
  • -231 <= nums[i] <= 231 - 1

题解

考虑将每一个元素x放在对应位置的下标处,比如,元素值x等于3,就放在下标为2的位置,因此数组3,2,1在重新放置之后们就会成为:1,2,3,即元素x放在下标为x-1的位置。

遍历一遍数组,如果发现现在i位置的元素值x不等于i+1,说明现在需要进行元素交换,让元素x放在它本来应该放置的位置x-1处,可以使用自定义的交换函数change(nums,i,x-1),即让i位置元素和x-1位置元素进行交换。

但是注意,交换之前,我们需要确定,现在i位置元素是否是正整数,如果不是的话,对于一个负数或0来说,在我们最终的数组中实际是没有该元素的位置的,因此交换操作不需要对负数和0进行操作,如果遍历到负数或0直接跳过;

其次,如果现在数组大小是4,即下标范围值[0,3],但是某一个数组元素值为7,该元素需要放置在下标为6的位置,但是数组放不下,因此这种情况也不需要进行交换排序,直接跳过。

综上所述,最终需要进行排序的前提条件是:

1、当前元素大小小于等于数组大小

2、当前元素值>=1

3、当前元素没有放在它实际应该放置的位置,即nums[i]!=nums[nums[i]-1]

在一次交换之后,当前位置上是否就是应该放置的值,这也是不确定的,因此上面我们实现的是将i位置的值放在正确的位置上,但是交换之后的值是否在正确的位置上还是不确定的,因此还需要继续交换,所以这里判断是否需要交换的条件要使用while循环而不是if循环。

使用while循环进行是否可以进行交换的判断的时候,如果出现重复元素在原数组中出现,那么也可以正常进行判断交换,因为,一旦其中一个元素交换到正确的位置上,那么下一个元素进行while判断的时候,nums[i]!=nums[nums[i]-1的条件就不满足,自然不会造成死循环,同时这里使用的是判断当前位置的值是否放在正确位置,而不是当前位置是否放置正确元素,因为现在遍历到当前位置,能确定的就是当前位置的值,以及当前位置的元素应该放到哪里,但是不能确定当前位置应该放置的元素现在在数组的什么位置,因此该判断条件要这么写。

代码实现

 public static int firstMissingPositive(int[] nums) {//原地排序数组,将值为x的元素放在下标x-1的位置for (int i = 0; i < nums.length; i++) {while(nums[i]>=1&&nums[i]<=nums.length&&nums[i]!=nums[nums[i]-1]){check(nums,i,nums[i]-1);}}for (int j = 0; j < nums.length; j++) {if(nums[j]!=j+1){return j+1;}}return nums.length+1;}public static void check(int[] a,int i ,int j){int temp = a[i];a[i] = a[j];a[j] = temp;}

知识点

对于这种数组交换来实现每一个元素都在自己应该在的位置的想法一开始觉得不能实现,因为觉得交换之后现在位置上的元素可能还是不满足要求,再进行交换,会不会将之前排好序的位置打乱,实际上,这样的担忧是不必要的,因为每个元素只有一个确定的位置,要么能够交换就交换的放置,要么因为在当前数组放不下该元素或者该元素小于1就不交换,总之,只要在while判断条件下进行的交换总能将新交换到当前位置的元素再交换到正确的位置,直到新交换到当前位置的元素已经不满足要交换的条件了,继续遍历下一个元素进行新一轮的交换即可。

相关文章:

  • 解决 There is no getter for property named ‘null‘ in ‘class 报错
  • HTML静态网页成品作业(HTML+CSS)—— 家乡南宁介绍网页(2个页面)
  • NSS题目练习7
  • 分享一个 .NET Core Console 项目使用依赖注入的详细例子
  • 前后端实现文件上传进度条-实时进度
  • linux防止nmap扫描
  • Elasticsearch之写入原理以及调优
  • 数据结构--二叉树(二)
  • iOS 通过PacketLogger 抓包蓝牙数据包
  • 新能源汽车内卷真相
  • Redis常用命令——List篇
  • Spring Boot整合Redis
  • C#WPF数字大屏项目实战08--生产量/良品统计
  • FreeRTOS实时系统 在任务中增加数组等相关操作 导致单片机起不来或者挂掉
  • 四舍五入问题
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • AWS实战 - 利用IAM对S3做访问控制
  • EventListener原理
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Logstash 参考指南(目录)
  • Quartz初级教程
  • Redis 中的布隆过滤器
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 基于组件的设计工作流与界面抽象
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 七牛云假注销小指南
  • 如何设计一个微型分布式架构?
  • 突破自己的技术思维
  • 网页视频流m3u8/ts视频下载
  • 微信支付JSAPI,实测!终极方案
  • 译米田引理
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (145)光线追踪距离场柔和阴影
  • (175)FPGA门控时钟技术
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (三)uboot源码分析
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (实测可用)(3)Git的使用——RT Thread Stdio添加的软件包,github与gitee冲突造成无法上传文件到gitee
  • (算法二)滑动窗口
  • (一)u-boot-nand.bin的下载
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .libPaths()设置包加载目录
  • .NET C# 配置 Options
  • .NET CORE Aws S3 使用
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET gRPC 和RESTful简单对比
  • .net 桌面开发 运行一阵子就自动关闭_聊城旋转门家用价格大约是多少,全自动旋转门,期待合作...