1. 问题背景与核心挑战
今天想和大家聊聊一个看似简单却暗藏玄机的算法问题——如何在整数数组中找出缺失的最小正整数。这个问题在技术面试中出现的频率相当高,比如经典的LeetCode第41题"First Missing Positive"就要求我们用O(n)时间复杂度和常数空间复杂度来解决。
我第一次遇到这个问题时,直觉反应是用哈希表记录出现过的数字,然后从1开始逐个检查。但面试官紧接着就问:"如果要求空间复杂度是O(1)呢?" 这才意识到问题的精妙之处。经过反复思考和尝试,最终掌握了一种优雅的解决方案——原地哈希(In-place Hashing)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法思路解析
2.1 问题重述与边界条件
给定一个未排序的整数数组,找出其中缺失的最小正整数。例如:
- 输入[3,4,-1,1],输出2
- 输入[7,8,9,11,12],输出1
- 输入[1,2,0],输出3
需要注意几个关键边界:
- 数组可能包含负数和零
- 数组可能包含重复元素
- 缺失的正整数可能比数组长度大
2.2 核心观察与数学原理
关键观察点在于:对于一个长度为n的数组,缺失的最小正整数只可能在1到n+1之间。这是因为:
- 如果数组包含1到n的所有数字,那么缺失的是n+1
- 否则缺失的数字一定在1到n之间
这个观察让我们可以将问题规模缩小到数组长度范围内。
2.3 原地哈希的核心思想
常规哈希表解法需要O(n)额外空间。要实现O(1)空间,我们需要利用数组本身作为哈希表:
- 遍历数组,将数字x放到索引x-1的位置
- 再次遍历数组,第一个不满足nums[i] == i+1的位置就是缺失的数字
这个过程相当于"就地"建立了数字与其索引的映射关系。
3. 详细实现步骤
3.1 算法步骤拆解
让我们用[3,4,-1,1]这个例子一步步说明:
初始状态:[3,4,-1,1]
第一轮遍历:
- i=0: nums[0]=3,应该放到索引2。交换nums[0]和nums[2] → [-1,4,3,1]
- i=0: nums[0]=-1,跳过(不在1到n范围内)
- i=1: nums[1]=4,应该放到索引3。交换nums[1]和nums[3] → [-1,1,3,4]
- i=1: nums[1]=1,
