【LeetCode】41. First Missing Positive (3 solutions)

First Missing Positive

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

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

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

 

解法一:O(nlogn) time and O(1) space

无脑解法-->先排序O(nlogn)

思想如下:

1、略去非正的前缀数。

2、记下一个待匹配的正整数为tag。

考虑重复,如果A[i]等于tag,则tag++

如果A[i]大于tag,则返回tag

A[i]不可能小于tag,由排序可以保证。

class Solution {
public:
    int firstMissingPositive(int A[], int n) {
        if(n == 0)
            return 1;
        sort(A,A+n);
        int i = 0;
        while(i < n && A[i] <= 0)
            i ++;
        if(i == n)
            return 1;
        int tag = 1;
        for(; i < n; i ++)
        {
            if(A[i] > tag)
            //miss the tag
                return tag;
            else if(A[i] == tag)
            //next positive
                tag ++;
            else
                ;
        }
        //i==n, miss the tag
        return tag;
    }
};

 

解法二:O(n) time and O(n) space

稍作思考就可以知道,n容量的数组,最多覆盖的正整数为连续的1~n

也就是说,丢失的正整数要么出现在1~n中,要么就是n+1

因此可以构造大小为n的数组v,v[i]记录i+1这个数字是否出现在A中。

如果tag全true则返回n+1,否则返回第一个tag为负的下标+1

class Solution {
public:
    int firstMissingPositive(int A[], int n) {
        if(n == 0)
            return 1;
        //tag[i] means whether i+1 exists in A
        //at most 1~n, then return n+1
        vector<bool> tag(n, false);
        for(int i = 0; i < n; i ++)
        {
            if(A[i] > 0 && A[i] <= n)
                tag[A[i]-1] = true;
        }
        for(int i = 0; i < n; i ++)
        {
            if(tag[i] == false)
                return i+1;
        }
        return n+1;
    }
};

 

解法三:O(n) time and O(1) space

解法二中我们构建了新的数组tag来记录每个正整数是否出现在A中,

其实可以省略tag数组,直接在A中记录。这点借鉴了yuyibestman想法。

具体做法为,先将A划分为正整数与非负数。这点类似快排的partition。

A[i]的正负号记录i+1这个数字是否出现在A中。

由于只是符号取负,其值可以通过绝对值函数恢复。这样就代替了解法二中的tag数组了。

class Solution {
public:
    int firstMissingPositive(int A[], int n) {
        if(n == 0)
            return 1;
        //if A[i] is negative, i+1 exists in original A
        
        //partition, non-negative only
        int low = 0;
        int high = n-1;
        int end = n-1;
        while(low <= high)
        {
            while(low <= high && A[low] > 0)
                low ++;
            //to here, 
            //case low > high: partition finished, high point to the end of the new array
            if(low > high)
            {    
                end = high;
                break;
            }
            //case A[low]<=0: low point to the first non-positive element
            
            
            while(high >= low && A[high] <= 0)
                high --;
            //to here, 
            //case high < low: partition finished, high point to the end of the new array
            if(low > high)
            {
                end = high;
                break;
            }
            //case A[high]>0: high point to the first positive element
            swap(A[low],A[high]);
        }
        
        for(int i = 0; i <= end; i ++)
        {
            //check whether num is in A, and set A[num-1] to be negative
            int num = abs(A[i]);
            if(num <= end+1)
            {
                if(A[num-1] > 0)
                    A[num-1] *= -1;
            }
            //out of range 1~end+1
        }
        
        for(int i = 0; i <= end; i ++)
        {
            if(A[i] > 0)
                return i+1;
        }
        return end+2;
    }
};

posted @ 2014-12-15 14:39  陆草纯  阅读(375)  评论(0编辑  收藏  举报