41、缺失的第一个正数

  1. 41、缺失的第一个正数
    1. 示例 1:
    2. 示例 2:
    3. 示例 3:
  2. 题解
    1. 1、排序,然后遍历求解
    2. 2、哈希表
    3. 2、置换法

41、缺失的第一个正数

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

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

示例 1:

输入: [1,2,0]

输出: 3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:

输入: [3,4,-1,1]

输出: 2

解释:1 在数组中,但 2 没有。

示例 3:

输入: [7,8,9,11,12]
输出: 1
解释:最小的正数 1 没有出现。

说明:

提示:

  • $1 <= nums.length <= 10^5$
  • $-2^{31} <= nums[i] <= 2^{31} - 1$

链接:https://leetcode-cn.com/problems/first-missing-positive

题解

1、排序,然后遍历求解

时间复杂度超了。

  • 先排序
  • 初始化index 从1开始
  • 初始化pre,记录前一个正值
  • 循环遍历
    • 对于大于0的值,从1开始匹配
    • 没有匹配,如果前一个正值也没有匹配
      • 返回结果
    • 匹配了
      • 更新pre
  • 返回结果
class Solution {
    public int firstMissingPositive(int[] nums) {
        //你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。
        Arrays.sort(nums);// 排序 O(nlogn)
        int len = nums.length;
        int index = 1;
        int pre = -1;
        for (int i = 0;i < len;i++) {
            if (nums[i] > 0) {
                if (index != nums[i]) { // 老哥不在
                    if(pre != nums[i]) break;// 老老哥也不再,哈哈找到你了
                } else {// 下次再来
                    pre = index++;// 换个马甲
                }
            }
        }
        return index;
    }
}

2、哈希表

对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1, N+1]中。这是因为如果 [1, N] 都出现了,那么答案是 N+1,否则答案是 [1, N] 中没有出现的最小正整数。

  • 遍历数组,将所有小于0的值,重置为n+1

  • 遍历数组

    • abs取值num,用num自己作为下标
    • 对于num小于等于n的值
      • 用num - 1自己作为下标,执行正数重置为负数
  • 遍历数组

    • 获取第一个正数,并返回
class Solution {
  public int firstMissingPositive(int[] nums) {
    int n = nums.length;
    // 将所有非正数置位可能的目标值
    for (int i = 0;i < n;++i) {
      if (nums[i] <= 0) {
        nums[i] = n + 1;
      }
    }
    // set e (e < n) to relative e
    for (int i = 0;i < n;++i) {
      // is it necessary?
      int num = Math.abs(nums[i]);
      if (num <= n) {
        // 归位标记
        // 关键步骤:将num-1位置的数字变为负数,表示该正数已存在
        nums[num - 1] = -Math.abs(nums[num - 1]);
      }
    }
    // find positive one for return
    for (int i = 0;i < n; ++i) {
      if (nums[i] > 0) {
        return i + 1;
      }
    }
    return n + 1;
  }
}

2、置换法

将每一个正值且小于等于n的nums[i],nums[i] - 1作为下标,进行i位置和nums[i] - 1位置进行更换。

实现了归位,即 num应该位于下标为num-1的位置。

class Solution {
  public int firstMissingPositive(int[] nums) {
    int n = nums.length;
    for (int i = 0;i < n;++i) {
      // 递归调换,并设置下一个需要调换的值。确保nums[i]的值是有效的,防止出现溢出和无限循环
      while (nums[i] > 0 && nums[i] <= n &&  nums[nums[i] - 1] != nums[i]) {
        int tmp = nums[nums[i] - 1];
        nums[nums[i] - 1] = nums[i];// 关键:将nums[i] 归位到于下标匹配的位置
        nums[i] = tmp;
      }
    }
    // 查找缺失的值
    for (int i = 0;i < n;++i) {
      if (nums[i] != i + 1) {
        return i + 1;
      }
    }
    return n + 1;
  }
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

💰

Title:41、缺失的第一个正数

Count:863

Author:攀登

Created At:2020-07-26, 00:19:44

Updated At:2024-06-17, 16:54:53

Url:http://jiafeimao-gjf.github.io/2020/07/26/41%E3%80%81%E7%BC%BA%E5%A4%B1%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%AD%A3%E6%95%B0/

Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

×

Help us with donation