41. 缺失的第一个正数
41. 缺失的第一个正数
题目链接:41. 缺失的第一个正数
题目描述
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你设计并实现时间复杂度为 $O(n)$ 并且只使用常数级别额外空间的算法解决此问题。
核心思考:置换法(原地哈希)
本题的难点在于 $O(n)$ 时间和 $O(1)$ 空间的硬性指标。如果允许额外空间,哈希表可以轻易解决。为了满足原地(In-place)要求,我们可以把数组本身当成哈希表。
- 核心逻辑:我们要找的是第一个缺失的正数。对于一个长度为 $L$ 的数组,这个正数一定在范围 $[1, L+1]$ 之内。我们可以通过置换,让每一个数字 $x$(如果在范围 $[1, L]$ 内)都回到它对应的“柜位” $x-1$。
- 交换过程:
- 遍历数组,对于每个位置的数
nums[i],如果它是一个“合法”的正数(即在 $[1, L]$ 范围内),且它目前所在的位置不对(即nums[i] != nums[nums[i]-1]),我们就将其与它目标位置上的数进行交换。 - 这是一个“各回各家”的过程。注意使用
while而非if,因为交换回来的那个新数可能也需要继续交换到它对应的位子。
- 遍历数组,对于每个位置的数
- 最终检查:
- 再次遍历数组,第一个满足
nums[i] != i + 1的索引i,对应的缺失值就是i + 1。 - 如果全部位置都对上了,说明缺失的是
L + 1。
- 再次遍历数组,第一个满足
解题思路 (Python)
1 | class Solution: |
复杂度分析
- 时间复杂度:$O(N)$,其中 $N$ 是数组的长度。虽然有嵌套循环,但每个数字最多只会被交换到它的正确位置一次,总交换次数为 $O(N)$。
- 空间复杂度:$O(1)$。只在原始数组上进行修改,不需要额外的辅助空间。
ACM 模式
本节提供 ACM 竞赛风格的完整可运行代码,包含输入输出处理。
输入格式:
1 | num1 num2 num3 ... numN |
输入一行整数数组,以空格分隔。
完整代码:
1 | import sys |
运行示例:
1 | echo "2 -1 3 4 -5" | python solution.py |