题目描述
解法
首先想到的是哈希,本题哈希的思路如下:
假设原始数组为 A。先构造一个临时数组 tmp,初始化为 0,大小为A.size(). 遍历 A,把 A[i] 复制到 tmp[A[i]-1] 的位置。如果 A[i] - 1 超过了 tmp 的范围,就直接扔掉。如此一来,tmp[0…size) 中就保存了一部分 A 的值。然后从位置 0 开始检查 tmp,如果发现该位置的值和索引号不匹配,就说明找到了缺失的数了
但是题目要求严格的空间复杂度了,那就原地哈希,准确的说是原地置换的思路和算法,但我把它和哈希放一块是因为这题很容易一上来就想哈希,那在哈希满足不了题目要求时,往往可以也用置换的办法吧我觉得。
或者理解为,原地置换思想就相当于我们自己编写哈希函数,这个哈希函数的规则就是数值为 i 的数映射到下标为 i - 1 的位置。放张图以便理解
注意理解代码 nums[nums[i] - 1] != nums[i] 的作用。这是因为nums[i]应该呆的位置被跟它重复的值占用了,这种情况直接跳过就行,不需要再置换。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int len = nums.size();
for(int i = 0; i < len; i++)
{
while(nums[i] > 0 && nums[i] <= len && nums[i] != i+1 && nums[nums[i]-1] != nums[i])
swap(nums, nums[i]-1, i);
}
for(int i = 0; i < len; i++)
if(nums[i] != i+1)
return i + 1;
return len + 1;
}
void swap(vector<int>& nums, int i, int j)
{
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
};
原地置换的相同思路和算法在 【原地哈希】剑指Offer 03.数组中重复的数字 中也有