Code Top -- 09 第一个缺失的正整数

第一个缺失的正整数

Posted by OUC_LiuX on April 15, 2022

from CodeTop, Leetcode, 41. 缺失的第一个正数
原地哈希。

题意:

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:
输入:nums = [1,2,0]
输出:3

示例 2:
输入:nums = [3,4,-1,1]
输出:2

示例 3:
输入:nums = [7,8,9,11,12]
输出:1

解读:

使用原地哈希方法,也即,数组本身当做哈希表,不需开辟额外空间。具体思想是,使数组第 i (下标,从 0 开始)个元素存储 i+1 (值),存储结束后,遍历哈希表,第一个 nums[i] != i+1 的位置,就是缺失的第一个正整数。具体做法是:
遍历数组,如果有 nums[i] != i+1,进 while 循环执行:第 i 个位置的值和第 nums[i] - 1位置的值交换,也就是让 nums[i] - 1 位置存放 nums[i] 这个值。注意,一定是交换,而不能直接赋值 nums[i] = i+1,因为 i + 1 这个值不一定在数组中存在。while 循环直到值不再合法而结束。值不在合法的意思是指:nums[i] 小于等于零或者大于数组长度,因为数组若存储正整数,最小存储 1 ,最大能存储到数组长度。或者,另一种退出情况是,nums[i]-1 这个位置,已经存储了 nums[i] 这个值,此时显然不能再交换了,也要退出。

代码:

for (int i = 0; i < nums.size(); i++){
    while(nums[i] != i+1){
        if (nums[i] <= 0 || nums[i] > nums.size() || 
            nums[nums[i] - 1] == nums[i])
            break;
        int idx = nums[i] - 1;
        nums[i] = nums[idx];    
        // 这一步目的不是给 i 位置赋值,而是给 nums[i] - 1 位置赋值          
        // 而 i 位置只是接收一下,或者说临时转储一下 nums[i]-1 位置的值           
        nums[idx] = idx++;
    }

    for (int i = 0; i < nums.size(); i++)
        if (nums[i] != i+1) return i+1;
    return nums.size()+1;// 如果前面都有,那缺失的第一个值一定是 nums.size()+1       
}