Leetcode 41 缺失的第一个正数

Leetcode41缺失的第一个正数

  • 题目描述
    • 题解1:置换思想
    • 题解2:改造哈希表

题目描述

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 <= nums.length <= 5 * 105
  • -231 <= nums[i] <= 231 - 1

来源:力扣(LeetCode)题目链接
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解1:置换思想

/* 
简单分析:nums未出现的 最小正整数 只会出现在[1,s+1]里:
1. nums有[1,s]  所有 的正整数,未出现的最小正整数是s+1
2. nums没有正整数或者没有1,未出现的最小正整数是1
3. nums值不连续,未出现的最小正整数在[1,s]里
但实际上,因为要找最小,所以是从前往后找,范围还是在[1,s]里
*/ 
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int s = nums.size();       
        for(int i=0; i<s; i++){
            // 置换的思想:
            // 把值在[1,s]的x换到x-1的位置上
            // 限制条件:值范围 && x不在x-1下标对应的位置上
            // 如果x已经在x-1的位置就不需要再换位置了,也可以说避免 nums[i]-1 == i
            while(nums[i] > 0 && nums[i] <= s && nums[nums[i]-1] != nums[i])
                swap(nums[nums[i]-1], nums[i]);
        }
        for(int i=0; i<s; i++){
            if(nums[i] != i+1)
                return i+1;
        }
        return s+1;
    }
};

Leetcode 41 缺失的第一个正数_第1张图片

题解2:改造哈希表

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int s = nums.size();
        // 负数没用,负数全换成s+1
        // 给出现过的正整数做标记:对应的 x-1位置 的数转为负数(下标i映射i+1的值)
        // 最后遍历的时候第一个正数下标+1 即为最终解
        for(int i=0; i<s; i++){
            if(nums[i] <= 0) 
                nums[i] = s+1;
        }
        for(int i=0; i<s; i++){
        // 这里注意:从前换后,后面的正数被转为了负数,所以都用abs取正
        // 实际上是因为循环内无法保证每次的nums[i] > 0
            if(abs(nums[i])>0 && abs(nums[i])<=s)
                nums[abs(nums[i])-1] = -abs(nums[abs(nums[i])-1]);
        }
        for(int i=0; i<s; i++){
            if(nums[i] > 0)
                return i+1;
        }
        return s+1;
    }
};

Leetcode 41 缺失的第一个正数_第2张图片

你可能感兴趣的:(HOT100,Math思想,leetcode,算法,数据结构)