zoukankan      html  css  js  c++  java
  • [LintCode] Find Missing Positive

    Given an unsorted integer array, find the first missing positive integer.

    Example

    Given [1,2,0] return 3,
    and [3,4,-1,1] return 2.

    Challenge 

    Your algorithm should run in O(n) time and uses constant space.

    Solution 1. O(n * logn) runtime using sorting.

    Algorithm.

    1. sort the input array in O(n*logn).

    2. find the index of the first positive integer in O(n). If none found or the first positive integer is bigger than 1, return 1. 

    3. do a O(n) scan starting from the second positive integer to find the first missing positive.

     Ignore duplicated integers, if found the next consecutive integer, update the next search integer and keep searching.

     1 public class Solution {
     2     public int firstMissingPositive(int[] A) {
     3         if(A == null){
     4             return 1;
     5         }
     6         Arrays.sort(A);
     7         int firstPosIdx = 0;
     8         for(; firstPosIdx < A.length; firstPosIdx++){
     9             if(A[firstPosIdx] > 0){
    10                 break;     
    11             }
    12         }
    13         if(firstPosIdx == A.length || A[firstPosIdx] != 1){
    14             return 1;
    15         }
    16         firstPosIdx++;
    17         int missing = 2;
    18         for(; firstPosIdx < A.length; firstPosIdx++){
    19             if(A[firstPosIdx] != A[firstPosIdx - 1] && A[firstPosIdx] != missing){
    20                 break;
    21             }         
    22             else if(A[firstPosIdx] == missing){
    23                 missing++;
    24             }
    25         }
    26         return missing;
    27     }
    28 }

    Solution 2.  O(n * logn) runtime, O(n) space using min priority queue.

    This solution uses the same idea with solution 1, but implements using min priority queue instead of sorting.

    Algorithm.

    1. store all positive integers to a min pq.

    2.  poll the min integer out of the min pq one by one; If there is a gap in between two consecutively polled 

    integers, we found the first missing positive number.

     1 public class Solution {
     2     public int firstMissingPositive(int[] A) {
     3         if(A == null || A.length == 0){
     4             return 1;
     5         }    
     6         PriorityQueue<Integer> pos = new PriorityQueue<Integer>();
     7         for(int i = 0; i < A.length; i++){
     8             if(A[i] > 0){
     9                 pos.add(A[i]);
    10             }
    11         }
    12         if(pos.size() == 0 || pos.peek() != 1){
    13             return 1;
    14         }
    15         int prev = pos.poll();
    16         int curr = 0;
    17         int missing = 2;
    18         while(pos.size() > 0){
    19             curr = pos.poll();
    20             if(curr != prev && curr != missing){
    21                 break;
    22             }
    23             else if(curr == missing){
    24                 missing++;
    25             }
    26             prev = curr;
    27         }
    28         return missing;
    29     }
    30 }

    Solution 3. O(n) runtime, O(n) space, using hash set

     1 public class Solution {
     2     public int firstMissingPositive(int[] A) {
     3         if(A == null || A.length == 0){
     4             return 1;
     5         } 
     6         HashSet<Integer> pos = new HashSet<Integer>();
     7         int minPos = Integer.MAX_VALUE;
     8         for(int i = 0; i < A.length; i++){
     9             if(A[i] > 0){
    10                 pos.add(A[i]);
    11                 minPos = Math.min(minPos, A[i]);
    12             }
    13         }
    14         if(pos.size() == 0 || minPos > 1){
    15             return 1;
    16         }
    17         pos.remove(1);
    18         int missing = 2;
    19         while(pos.size() > 0){
    20             if(pos.contains(missing)){
    21                 pos.remove(missing);
    22                 missing++;
    23             }    
    24             else{
    25                 break;
    26             }
    27         }
    28         return missing;
    29     }
    30 }

    Solution 4. O(n) runtime, O(1) space.

    The runtime of O(n) is already optimal since we need to at least scan the whole input array once to get a correct result.

    But can we come up a solution with O(1) extra space usage? 

    To solve a problem that involves arrays using O(1) space, the first approach that should come to our mind is using the 

    original input array and swap its elements in place, just like in quick sort.

    To get the first missing positive integer, we must first check that all the positive integers that are smaller than 

    the final answer exist. I.e, these smaller numbers must "appear" before the final answer appears. This relative order 

    constraint is similar with sorting but different in that we don't care about the relative orders of all negative numbers.

    To enforce the relative ordering of positive numbers, we change the array to have to following property.

    For A[i] that exist in the array, if it is positive and <= A.length, then A[i] = i + 1.

    This property makes sure that if we have 1s in the array, then A[0] must be 1; if we have 2s in the array,

    then A[1] must be 2, etc. 

    If A has the above property, then it takes O(n) time to find the first missing positive. We just need to find 

    the smallest index i that does not satisfy A[i] == i + 1 and i + 1 is our answer.

    The highlighted code changes A to have the above property.  After each swap, the number at index A[i] - 1

    meets the property of A[i] = i + 1.

    Key ideas:

    1. Scan through input array to achieve the following invariant by swapping elements.

    A[i] = i + 1;

    2. Ignore non-positive integers and integers that are bigger than A.length since these integers won't be the the first missing positive.(If the input array is 1, 2, 3, ....., A.length, then A.length + 1 will be the first missing positive) 

    3. For each element A[i], if it meets condition 2, and A[i] != i + 1, swap it with the element at index A[i] - 1,  unless A[A[i] - 1] already equals to A[i]. (This means that at index A[i] - 1, it already satisfies the invariant we're trying to enforce, thus no swap is needed.)

     1 public class Solution {
     2     public int firstMissingPositive(int[] A) {
     3         if(A == null || A.length == 0){
     4             return 1;
     5         }
     6         for(int i = 0; i < A.length; i++){
     7             while(A[i] > 0 && A[i] <= A.length && A[A[i] - 1] != A[i] && A[i] != (i + 1)){
     8                 int tmp = A[A[i] - 1];
     9                 A[A[i] - 1] = A[i];
    10                 A[i] = tmp;
    11             }
    12         }
    13         for(int i = 0; i < A.length; i++){
    14             if(A[i] != i + 1){
    15                 return i + 1;
    16             }
    17         }
    18         return A.length + 1;
    19     }
    20 }

    Related Problems

    Find the Duplicate Number

    Find the Missing Number II

    Find the Missing Number

  • 相关阅读:
    LR11
    安装Nginx+uWSGI+Django环境
    MYSQL 安装更新,使用,管理,备份和安全等
    oracle里要查看一条sql的执行情况,有没有走到索引,怎么看?索引不能提高效率?
    大神:python怎么爬取js的页面
    Sublime 编译出来的是 dos格式,不是unix格式
    前天搞了一天?昨天搞了一天?今天搞了半小时
    搞了一宿,弄完了一个POP3协议
    我竟然。。。傻了近一年
    跨进程信息交互真个费事。
  • 原文地址:https://www.cnblogs.com/lz87/p/7209147.html
Copyright © 2011-2022 走看看