题目描述:缺失的第一个正数
给你一个未排序的整数数组 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 没有出现。
解题思路
可以利用数组本身的索引来标记哪些正整数已经出现过。具体步骤如下:
首先,将数组中所有小于等于 0 或者大于数组长度 n
的数置为 n + 1
,因为这些数不会影响最终结果。
然后,遍历数组,对于每个绝对值在 [1, n]
范围内的数 num
,将数组中索引为 num - 1
的数取相反数,表示该正整数已经出现过。
最后,再次遍历数组,找到第一个正数所在的索引 i
,那么 i + 1
就是缺失的最小正整数。如果数组中所有数都是负数,说明 1
到 n
都出现过,那么缺失的最小正整数就是 n + 1
。
参考代码
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums)
# 第一步:将所有小于等于 0 或者大于 n 的数置为 n + 1
for i in range(n):
if nums[i] <= 0 or nums[i] > n:
nums[i] = n + 1
# 第二步:标记出现过的正整数
for i in range(n):
num = abs(nums[i])
if num <= n:
nums[num - 1] = -abs(nums[num - 1])
# 第三步:找到第一个正数所在的索引
for i in range(n):
if nums[i] > 0:
return i + 1
# 如果数组中所有数都是负数,说明 1 到 n 都出现过,返回 n + 1
return n + 1