数据结构与算法之排序: Leetcode 41. 缺失的第一个正数 (Typescript版)

缺失的第一个正数

  • https://leetcode.cn/problems/first-missing-positive/

描述

  • 给你一个未排序的整数数组 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 )一般思路

function firstMissingPositive(nums: number[]): number {
  // 过滤掉非正整数
  nums = nums.filter(item => item > 0);
  // 正整数数组是为空
  if (!nums.length) return 1;
  // 升序,目的:方便从左到右取最小值arr[0]
  nums.sort((a, b) => a - b);
  // 如果第一个元素不为1,返回1
  if (nums[0] !== 1) return 1;
  // 从左边开始遍历,只要下一个元素和当前元素差值》1说明当前元素的下一个值(+1)
  for (let i = 0, len = nums.length - 1; i < len; i++) {
    if (nums[i + 1] - nums[i] > 1) {
      return nums[i] + 1;
    }
  }
  // 如果数组是连续的正整数【1,2,3,4,5,6】
  return nums.pop() + 1;
}
  • 这个算法不是最优解,做了很多不需要的事情,比如 filter 和 sort
  • 不需要完全进行排序

2 )基于冒泡改造

function firstMissingPositive(nums: number[]): number {
  nums = nums.filter(item => item > 0);
  const n = nums.length;
  let min: number;
  // 实现选择排序,先拿到最小值,如果第一个元素不是1直接返回1,如果是1,就要比相邻元素差值
  for (let i: number = 0; i < n; i++) {
    min = nums[i];
    for (let j: number = i + 1; j < n; j++) {
      if (nums[j] < min) {
        let c = min;
        min = nums[j];
        nums[j] = c;
      }
    }
    nums[i] = min;
    if (i > 0) {
      if (nums[i] - nums[i - 1] > 1) return nums[i - 1] + 1;
    } else {
      if (min !== 1) return 1;
    }
  }
  return nums.length ? nums.pop() + 1 : 1;
}
  • 冒泡排序, 但是会存在 超出时间限制 的问题
  • 或基于其他排序改造均可

3 )查询表

function firstMissingPositive(nums: number[]): number {
  const n: number = nums.length;
  const { abs } = Math;
  let i: number;
  for (let i = 0; i < n; ++i) {
      if (nums[i] <= 0) {
          nums[i] = n + 1;
      }
  }
  for (i = 0; i < n; ++i) {
      let num = abs(nums[i]);
      if (num <= n) {
          nums[num - 1] = -abs(nums[num - 1]);
      }
  }
  for (i = 0; i < n; ++i) {
      if (nums[i] > 0) {
          return i + 1;
      }
  }
  return n + 1;
}
  • 官方提供方法
  • 时间复杂度:O(N),其中 N 是数组的长度。
  • 空间复杂度:O(1)。

4 )置换法

function firstMissingPositive(nums: number[]): number {
  const n = nums.length;
  let i: number;
  for (i = 0; i < n; ++i) {
      while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
          [nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]]; // 交换
      }
  }
  for (i = 0; i < n; ++i) {
      if (nums[i] != i + 1) {
          return i + 1;
      }
  }
  return n + 1;
}
  • 这是官方提供
  • 时间复杂度:O(N),其中 NNN 是数组的长度。
  • 空间复杂度:O(1)。

你可能感兴趣的:(Data,Structure,and,Algorithms,leetcode,算法,排序)