[Algorithm] Find first missing positive integer

Given an array of integers, find the first missing positive integer in linear time and constant space. In other words, find the lowest positive integer that does not exist in the array. The array can contain duplicates and negative numbers as well.

For example, the input [3, 4, -1, 1] should give 2. The input [1, 2, 0] should give 3.

You can modify the input array in-place.

 

Our lives would be easier without the linear time constraint: we would just sort the array, while filtering out negative numbers, and iterate over the sorted array and return the first number that doesn't match the index. However, sorting takes O(n log n), so we can't use that here.

Clearly we have to use some sort of trick here to get it running in linear time. Since the first missing positive number must be between 1 and len(array) + 1 (why?), we can ignore any negative numbers and numbers bigger than len(array). The basic idea is to use the indices of the array itself to reorder the elements to where they should be. We traverse the array and swap elements between 0 and the length of the array to their value's index. We stay at each index until we find that index's value and keep on swapping.

By the end of this process, all the first positive numbers should be grouped in order at the beginning of the array. We don't care about the others. This only takes O(N) time, since we swap each element at most once.

Then we can iterate through the array and return the index of the first number that doesn't match, just like before.

 

 

复制代码
function first_missing_positive(arr) {
  /**
   * The idea is put the number in the arr to its index position
   * [1,-1,4,2] --> [-1,1,2,null,4]
   * The first missing positive number must be between 1 ~ arr.length + 1
   * after swapping array in place, then we can check arrocding to index,
   * to find the first missing array. O(N)
   */

  const len = arr.length;
  for (let i = 0; i < len; i++) {
    let current = arr[i];
    while (current >= 0 && current <= len && current !== arr[current]) {
      [arr[i], arr[current]] = [arr[current], arr[i]];
      current = arr[i];
    }
  }
  console.log(arr);
  for (let j = 1; j < len; j++) {
    if (arr[j] !== j) {
      return j;
    }
  }
  return len;
}

var arr = [3, -4, 9, 1, 0];

const res = first_missing_positive(arr);
console.log(res); // 2
复制代码

 

Another way we can do this is by adding all the numbers to a set, and then use a counter initialized to 1. Then continuously increment the counter and check whether the value is in the set.

复制代码
function first_missing_positive(arr) {
  const s = new Set(arr);
  for (let j = 1; j < arr.length; j++) {
    if (s.has(j)) {
      continue;
    }
    return j;
  }
}

var arr = [3, 4, -1, 1];

const res = first_missing_positive(arr);
console.log(res); // 2
复制代码

This is much simpler, but runs in O(N) time and space, whereas the previous algorithm uses no extra space.

posted @   Zhentiw  阅读(361)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2018-03-08 [HTML5] Accessibility Implementation for complex component
2017-03-08 [React] Recompose: Theme React Components Live with Context
2017-03-08 [Angular] Using directive to create a simple Credit card validator
2017-03-08 [Docker] Container & image (docker run)
2017-03-08 [Django] Building the rest API
2016-03-08 [RxJS] Reactive Programming - New requests from refresh clicks -- merge()
2016-03-08 [RxJS] Starting a Stream with SwitchMap & switchMapTo
点击右上角即可分享
微信分享提示