📌  相关文章
📜  给定数组中不存在的最大为 N 的正整数(1)

📅  最后修改于: 2023-12-03 15:41:16.921000             🧑  作者: Mango

给定数组中不存在的最大为 N 的正整数

在开发中,有时候需要找到一个数组中不存在的最大为 N 的正整数,以下介绍几种解决方案。

方案一: 利用 Set 数据结构

最直观的解决方法是通过 Set 数据结构来存储该数组中的所有正整数,然后从 1 开始递增,判断当前数字是否存在于 Set 中,直到找到不存在于 Set 中的最大正整数为止,代码如下:

function findMissingNumber(arr, n) {
  let set = new Set(arr);
  let i = 1;
  while (i <= n) {
    if (!set.has(i)) {
      return i;
    }
    i++;
  }
  return null;
}

该方法的时间复杂度为 O(N),空间复杂度为 O(N)。

方案二: 原地交换数字

如果数组中的数字小于等于 N,则可以将数字 i 与 arr[i-1] 的位置交换,使得数字 i 出现在 arr[i-1] 的位置上。然后再遍历数组,找出第一个不符合这个规律的位置,该位置的数字+1 就是题目要求的缺失的最大正整数。代码如下:

function findMissingNumber(arr, n) {
  for (let i = 0; i < arr.length; i++) {
    while (arr[i] > 0 && arr[i] <= n && arr[i] !== arr[arr[i] - 1]) {
      let temp = arr[i];
      arr[i] = arr[temp - 1];
      arr[temp - 1] = temp;
    }
  }

  for (let i = 0; i < arr.length; i++) {
    if (arr[i] !== i + 1) {
      return i + 1;
    }
  }
  return n + 1;
}

该方法的时间复杂度为 O(N),空间复杂度为 O(1)。

方案三: Bitset 位集合

当 N 的值非常大时,上述两种方法的时间复杂度都会非常高,可以使用 Bitset 来进行优化。Bitset 是一种利用二进制位来表示一个数是否存在的数据结构,可以极大地压缩存储空间。代码如下:

function findMissingNumber(arr, n) {
  let bitset = new Array(Math.ceil(n / 32)).fill(0);

  for (let i = 0; i < arr.length; i++) {
    bitset[Math.floor((arr[i] - 1) / 32)] |= 1 << ((arr[i] - 1) % 32);
  }

  for (let i = 0; i < bitset.length; i++) {
    if (bitset[i] !== 0xffffffff) {
      for (let j = 0; j < 32; j++) {
        if ((bitset[i] & (1 << j)) === 0) {
          return i * 32 + j + 1;
        }
      }
    }
  }
  return n + 1;
}

该方法的时间复杂度为 O(N/32),空间复杂度为 O(N/32)。

综上所述,不同的解决方法适用于不同的情况,具体选择哪种方法需要根据实际情况来决定。