缺失的第一个正数

437 阅读2分钟

这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战

一、题目描述

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

示例 1 :

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

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

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

提示:你的算法的时间复杂度应为O(n) ,并且只能使用常数级别的额外空间。

来源:力扣(LeetCode)

二、解题思路

  1. 题目要求具备O(n)复杂度,则不能先做排序处理;
  2. 因为是正整数数组,所以经过排序之后应该形如 [1,2,3,4,...,n] 数组 A
  3. 如果入参数组经过“调整”后的数组 B 中,任意元素与 A 不匹配,则那个元素就是 缺少的最小的正整数
  4. 此“调整”做法:尽可能将 1 放到数组的第 1 个位置,将 2 放到数组的第 2 个位置,以此类推。
  5. 最终从左到右遍历数组 B,找到第一个 索引 != 值-1 的值,即为答案。

三、参考代码

class Solution {
    public int firstMissingPositive(int[] nums) {
        // 异常输入检查&过滤
        if (null == nums || 0 == nums.length) {
            return 1;
        }
        int i = 0;
        while (i < nums.length) {
            int val = nums[i];
            if (val <= 0 || val == i+1 || val > nums.length) {
                // 不符合题意的异常值,直接跳过不处理
                i++;
                continue;
            }
            // 索引为 0 的位置应该放置 1,所以,索引为 val-1 的位置应该放 val
            int index = val - 1;
            // 提取 val-1 位置上的值
            int tmpVal = nums[index];
            // 将索引为 val-1 的位置置为 val
            nums[index] = val;
            
            if (val == tmpVal) {
                // 重复值,置0表示缺失
                nums[i++] = 0;
            } else {
                // 交换位置
                nums[i] = tmpVal;
            }
        }
        // 从左到右遍历“调整”后的数组,找到第一个 索引 != 值-1 的值
        for (i = 0; i < nums.length; i++) {
            if (nums[i] != i+1) {
                return i+1;
            }
        }
        return nums.length + 1;
    }
}