LeetCode First Missing Positive

class Solution {
public:
    int firstMissingPositive(int A[], int n) {
        if (A == NULL || n < 1) return 1;

        size_t len = (size_t)n + 1;
        vector<bool> bits(len, false);
        for (int i=0; i<n; i++) {
            if (A[i] < 0 || A[i] > n) continue;
            bits[A[i]] = true;
        }
        int miss = 1;
        while (miss <= INT_MAX) {
            if (!bits[miss]) return miss;
            if (miss == INT_MAX) {
                cout<<"no missing positive"<<endl;
                break;
            }
            miss++;
        }
        bits.clear();
        return 0;
    }
    
    int firstMissingPositive2(int A[], int n) {
        if (A == NULL || n < 1) return 1;

        unordered_map<int, int> mark;
        for (int i=0; i<n; i++) {
            mark[A[i]] = 1;
        }

        int miss = 1;
        while (miss <= INT_MAX) {
            if (mark.find(miss) == mark.end()) return miss;
            if (miss == INT_MAX) {
                cout<<"no missing positive"<<endl;
                return 0;
            }
            miss++;
        }
        return miss;
    }
    
    int firstMissingPositive3(int A[], int n) {
        if (A == NULL || n < 1) return 1;

        for (int i = 0; i<n; i++) {
            if (A[i] <= 0) A[i] = n + 1;
        }
        for (int i=0; i<n; i++) {
            int cur = A[i] < 0 ? -A[i] : A[i];
            if (cur <= n) A[cur - 1] = A[cur - 1] < 0 ? A[cur - 1] : -A[cur - 1];
        }
        int miss = 1;
        for (int i=0; i<n; i++) {
            if (A[i] > 0) break;
            miss++;
        }
        return miss;
    }
};

心烦,因为要找出数组A[n]中第一个缺失的整数,如果数组中有元素大于n那么这个数组必定至少缺失了一个数,因为如果A[n]包含[1,n]那么刚刚n个数,一个不少,且每个数小于n,如果某个元素大于n了,则中间肯定有间隙存在,否则元素个数将大于n。利用这一特征我们可以把负数和大于n的数都置为n+1这样在下一次扫描时可以忽略它们。

解法三存在一个问题,当n=INT_MAX且有负数存在时会出错。

 

第二轮:

解法三应该是从disscus上搞过来的,这个跟使用常数空间找一个无序数组(数组元素范围小于长度值)中的重复值类似,可以使用负数作为标记。实际上是使用了每个元素的符号位这样的一系列1bit的存储空间。反正已经将数组破坏掉了,还可以这样写避免数值溢出:

 1 class Solution {
 2 public:
 3     int firstMissingPositive(vector<int>& nums) {
 4         int len = nums.size();
 5         int idx = 0;
 6         for (idx = 0; idx < len; idx++) {
 7             if (nums[idx] == 1) {
 8                 break;
 9             }
10         }
11         if (idx == len) {
12             return 1;
13         }
14         
15         for (int i=0; i<len; i++) {
16             nums[i] = max(1, nums[i]);
17         }
18         
19         for (int i=0; i<len; i++) {
20             idx = abs(nums[i]) - 1;
21             if (idx >= len) {
22                 continue;
23             }
24             if (nums[idx] > 0) {
25                 nums[idx] = -nums[idx];
26             }
27         }
28         idx = 0;
29         while (nums[idx] < 0 && idx < len) idx++;
30         return idx + 1;
31     }
32 };

把小于等于0的数全部置为1,当然首先要检测一下1是否存在。

posted @ 2014-07-21 21:09  卖程序的小歪  阅读(159)  评论(0编辑  收藏  举报