LeetCode41 缺失的第一个正数

35 阅读2分钟

leetcode.cn/problems/fi…

image.png

解法一:将数组视为哈希表,原地哈希

由于题目要求我们「只能使用常数级别的空间」,而要找的数一定在 [1, N + 1] 左闭右闭(这里 N 是数组的长度)这个区间里。因此,我们可以就把原始的数组当做哈希表来使用。事实上,哈希表其实本身也是一个数组;

我们要找的数就在 [1, N + 1] 里,最后 N + 1 这个元素我们不用找。因为在前面的 N 个元素都找不到的情况下,我们才返回 N + 1;

那么,我们可以采取这样的思路:就把 1 这个数放到下标为 0 的位置, 2 这个数放到下标为 1 的位置,按照这种思路整理一遍数组。然后我们再遍历一次数组,第 1 个遇到的它的值不等于下标的那个数,就是我们要找的缺失的第一个正数。

这个思想就相当于我们自己编写哈希函数,这个哈希函数的规则特别简单,那就是数值为 i 的数映射到下标为 i - 1 的位置。

func firstMissingPositive(nums []int) int {
        // 不能用for range,因为其迭代时,i是按顺序递增的,不会回溯,无法模拟交换后继续检查的行为
        // for range 迭代的 nums[i] 是副本,即使交换了 nums[i],也不会影响 range 的下一次迭代逻辑
        for i:=0; i<len(nums); i++{
            // 将nums[i]置换到下标为nums[i]-1的位置上,可能需要多次置换后才成功,因此是个循环
            for nums[i] > 0 && nums[i] < len(nums) && nums[i] != nums[nums[i]-1]{
                nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]
            }
        }
        // 找到第一个值不等于下标+1的位置
        for idx, v := range nums{
            if idx + 1 != v{
                return idx + 1
            }
        }
        // 如果整个数组都找不到对应不上的,那么缺失的就是len+1
        return len(nums) + 1
}