🌈【LeetCode.缺少的最小整数值】- JavaScript =>抽屉法+占位法

334 阅读1分钟

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


题意描述

给你一个未排序的整数数组 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:抽屉原理

分析:数组的长度n,则答案最大只能是n+1。可以使用hash函数将答案空间映射到长度为n+1的数组上,再遍历数组找到最小的没出现的正整数。为实现常数空间复杂度,可以使用原数组的空间:

  • 如果 0<nums[i]<=nums.length;
  • 则将nums[i] 跟 nums[nums[i]-1]交换;
  • 最后再遍历数组,如果num[i] != i+1,则i+1就是缺失的最小正整数。
function firstMissingPositive(nums) {
  let max = 1;
  const record = {};
  let noPositiveNumber = true;

  nums.forEach(t => {
    if (t > 0) noPositiveNumber = false;
    max = t > max ? t : max;
    record[t] = true;
  });

  if (noPositiveNumber) return 1;

  for (let i = 1; i < max; i++) if (!record[i]) return i;
  return max + 1;
}
思路2:数字占位法

分析:首先让数字找到自己本来的位置,例如nums[1] = 1;因为它要找的是第一个消失的正整数。让每个数找到位置后,接着尝试去找跟位置不匹配的第一个数,找到直接返回。刚才说到nums[1] = 1,nums[0]未讨论到,实际上如果数组有0,会是Nums[0] =0。

var firstMissingPositive = function(a) {
  const INF = 1e9 + 10
  let n = a.length
  a.push(0)
  for (let i = 0; i < n; ++i) {
    a[i] = Math.max(0, Math.min(a[i], n + 1))
  }
  for (let i = 0; i < n; ++i) {
    let v = a[i] % INF
    if (!v || v > n) continue
    if (a[v] > INF) continue
    a[v] += INF
  }
  for (let i = 1; i <= n; ++i) if (a[i] < INF) return i
  return n + 1
};

感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤