描述
给定一个无重复元素的整数数组nums,请你找出其中没有出现的最小的正整数。
要求空间复杂度O(1), 时间复杂度O(n)
点击题目链接
思路
方法一:
遍历一遍数组,使用字典存储出现过的数字。1~n
个数如果都在nums
里面,那么最小的正整数就是n+1
。
相反,如果1-n
个数有几个不在nums里面,那最小的正整数在1-n
之中,因此遍历一遍1-n是否在nums中即可。(空间复杂度为O(n),不符合题意)
方法二:
最小的正整数要么是0~n
之间的一个数,要么就是n+1
。而数组下标刚好有n
个,因此可以用来标记,标记1-n
之间出现过哪些数。
具体做法分三步:
步骤一:遍历一边数组,将负数和0
置为n+1
。这是在为后面做局。
步骤二:遍历一边数组,如果num
属于(1~n)
范围,则将下标为num-1
的值修改成相反数。
步骤三:遍历数组,找到第一个值非负的下标,返回下标i+1
代码
class Solution:
# 方法一:
def minNumberDisappeared1(self , nums: List[int]) -> int:
my_dict = {}
for item in nums:
my_dict[item] = 1
print(my_dict)
for i in range(1,len(nums)):
if my_dict.get(i) == None:
return i
return len(nums)+1
# 方法二:
def minNumberDisappeared(self , nums: List[int]) -> int:
# 利用数组天然下标
# 先遍历一遍数组,负数和0的值取n+1
n = len(nums)
for i in range(n):
if nums[i] <= 0:
nums[i] = n+1
# 遍历数组,记录出现过哪些数在1~n范围的,映射为0~n-1。将其值修改为原值的相反数
for i in range(n):
if abs(nums[i]) <= n:
orin = abs(nums[i])
nums[orin -1] = -nums[orin-1]
# 遍历数组,找到第一个值为负数的
for i in range(n):
if nums[i] > 0:
return(i+1)
return n+1
注意题目要求空间复杂度为O(1),学到了一个利用数组原生顺序不重复下标的优势