必备知识
由于题目要求我们「只能使用常数级别的空间」,而要找的数一定在 [1, N + 1] 左闭右闭(这里 N 是数组的长度)这个区间里。因此,我们可以就把原始的数组当做哈希表来使用。事实上,哈希表其实本身也是一个数组;
我们要找的数就在 [1, N + 1] 里,最后 N + 1 这个元素我们不用找。因为在前面的 N 个元素都找不到的情况下,我们才返回 N + 1;
那么,我们可以采取这样的思路:就把 1 这个数放到下标为 0 的位置, 2 这个数放到下标为 1 的位置,按照这种思路整理一遍数组。然后我们再遍历一次数组,第 1 个遇到的它的值不等于下标的那个数,就是我们要找的缺失的第一个正数。
这个思想就相当于我们自己编写哈希函数,这个哈希函数的规则特别简单,那就是数值为 i 的数映射到下标为 i - 1 的位置。
示例代码
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int len=nums.size();
//我们要找的数就在 [1, N + 1] 里,最后 N + 1 这个元素我们不用找。
//因为在前面的 N 个元素都找不到的情况下,我们才返回 N + 1;
//就把 1 这个数放到下标为 0 的位置, 2 这个数放到下标为 1 的位置
//按照这种思路整理一遍数组。(通过交换的方式进行放置,否则会覆盖掉一些元素)
for(int i=0;i<len;i++){
//while 循环不会每一次都把数组里面的所有元素都看一遍。如果有一些元素在这一次的循环中被交换到了它们应该在的位置,那么在后续的遍历中,
//由于它们已经在正确的位置上了,代码再执行到它们的时候,就会被跳过。
while(nums[i]!=i+1){
//这里不直接进行返回是因为只有到最后才能知道结果
//nums[i] == nums[nums[i] - 1]防止出现死循环
if(nums[i]<=0||nums[i]>len||nums[i] == nums[nums[i] - 1]){
break;
}
//他要放的实际位置,将nums[i] 放置到对应位置上[1,2,3...]
//进行交换操作
swap(nums[i],nums[nums[i]-1]);
}
}
for(int i=0;i<len;i++){
if(nums[i]!=i+1){
return i+1;
}
}
return len+1;
}
};