【Leecode】缺失的第一个正数

问题描述

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

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

要求:
1 < = n u m s . l e n g t h < = 5 ∗ 1 0 5 1 <= nums.length <= 5 * 10^{5} 1<=nums.length<=5105
− 2 31 < = n u m s [ i ] < = 2 31 − 1 -2^{31} <= nums[i] <= 2^{31} - 1 231<=nums[i]<=2311

算法说明

本题主要的思路为:以位置作为正整数的代表做标记。

假如没有时间复杂度和空间复杂度的限制,我们的方法就多了:

第一种方法,开辟一个标记数组label,将label的下标0~nums.length 与 nums当中的整数对应起来。

如果1=<nums[i]<=nums.length,就将对应的label[nums[i] -1] 设置为true,反之就为false。

之后再判断label中的数是否全为true,如果是,则返回nums.length + 1
(因为label中的值全为true的话,代表从1到nums.length的整数全部都在nums当中,也就是说nums中出现了从1到nums.length所有的正整数,那么没有出现的最小的正整数自然就是nums.length + 1了 )

第二种方法,排序,将排序后的值依然放在nums中,然后设置min1和min2两个数。

如果nums.length = 1就根据nums[0]的数判断就行: nums[0] = 1则返回2,nums[0]等于其他值则返回1;

如果nums.length > 1就根据初始化min1 = nums[0] , min2 = nums[[1]]。
如果min2 -min1 > 1,则返回min1 +1;如果min2 - min1 = 1 则将min2,min1都往后移动一位,再进行下一次判断;如果当min2 = nums的最后一个元素时,min2 - min1 = 1,则返回nums.length + 1。

而现在我们有了时间复杂度和空间复杂度的限制,因此我们采用第一种方法,并将其稍作修改.

注意,这里默认nums中的数是可以修改的。如果nums中的数是固定值,那么不存在在该时间空间复杂度限制条件下的算法。

在此方法中,由于不能开辟新的O(n)数组,我们的label数组自然而然地就变成了nums。那么具体如何操作呢?

首先,进行这样一个操作:如果nums[i] <0,那么nums[i] = nums.length+1。

接着,进行以下循环:i属于[0,nums.length -1],如果nums[i]的绝对值大于等于1且小于等于numslength + 1,则nums[ | nums[i] - 1 | ] = -nums[ | nums[i] - 1 | ] ;如果为其他情况,则进行下一步循环

接着,进行以下的判断:如果nums中的数全都为负数,则返回nums.length + 1;否则,返回第一个使得nums[i] > 0 的 i。

实际代码

实现该算法的python3代码如下:

def firstMissingPositive(self, nums: list[int]) -> int:
	    size = len(nums)
	    for i in range(0,size):
	        if nums[i] <= 0:
	            nums[i] = size + 1
	    for i in range(0,size):
	        if (nums[i] <= size and nums[i] >=1) or ( -nums[i] <= size and -nums[i] >= 1):
	            if nums[i] > 0:
	                index = nums[i] - 1
	                if nums[index] > 0:
	                    nums[index] = -nums[index]
	            else:
	                index = -nums[i] - 1
	                if nums[index] > 0:
	                    nums[index] = -nums[index]
	
	        else:
	            continue
	    flag = 1
	    for i in range(0,size):
	        if nums[i] > 0:
	            flag = 0
	    if flag == 1:
	        return size + 1
	    else:
	        for i in range(0,size):
	            if nums[i] >= 0:
	                return i+1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值