First Missing Positive

一. 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.

Difficulty:Hard

TIME:20MIN

解法一(置爲負數)

如果排序後再解決,那麼這道題就沒有任何難度了。但顯然不能這樣做。

首先就是利用數組的下標,如果假設給定的數組都是正數,那麼如果出現某個數,就將和該數相等的下標的數置爲負數。
置換完成後,那麼如果第二次遍歷到某個下標的數爲正數,那麼就說明這個下標的數從來沒有出現過。那麼我們要找的數就是第一個爲正數的下標值。
爲什麼這樣就一定能找到結果呢,最主要的原因是找第一個沒有出現的正數,而這個正數剛好在數組下標的範圍內(或者比範圍大1,比如理想序列<1,2,3,4>,5就是比範圍4大1,而其他的情況一定在下標序列內)

不過這裏的數當然不止正數,還可能出現0和負數,因此我們可以先進行一次預處理,將所有0和負數都置爲1(當然要判斷一下數組本身有沒有1,否則可能會產生混淆)

int firstMissingPositive(vector<int>& nums) {
    bool one = false;
    //將所有的0和負數置爲1,不過要判斷一下數組本身有沒有1
    for(int i = 0; i < nums.size(); i++) {
        if(nums[i] == 1)
            one = true;
        if(nums[i] <= 0)
            nums[i] = 1;
    }
    if(!one)
        return 1;
    //將和出現的數相等下標的數(這裏減了一個1)置爲負數,如果數的大小超過了數組長度,就忽略這個數
    for(int i = 0; i < nums.size(); i++) {
        if(abs(nums[i]) <= nums.size())
            nums[abs(nums[i]) - 1] = -abs(nums[abs(nums[i]) - 1]);
    }
    //如果某個數大於0,說明這個數沒有出現過,直接輸出下標
    for(int i = 1; i < nums.size(); i++) {
        if(nums[i] > 0)
            return i + 1;
    }
    //當然理想情況下每個數都小於0,這個時候就輸出數組長度加1的數就行了
    return nums.size() + 1;
}

代碼的時間複雜度爲O(n)

解法二(交換)

另一種做法和前面的做法原理是一樣的,不過這裏如果找到某個正數,不是把和這個數相同的下標的數置爲負數,而是和這個數相同的下標的數進行調換,保證下標和它保存的數相等。

這種做法的好處就是可以忽略了0和負數二義性的問題,因此可以讓代碼更加簡潔。

int firstMissingPositive(vector<int>& nums) {
    //和出現的數相等下標的數進行交換
    for(int i = 0; i < nums.size(); i++) {
        while(nums[i] > 0 && nums[i] <= nums.size() && nums[i] != nums[nums[i] - 1]) {
            swap(nums[i],nums[nums[i] - 1]);
        }
    }
    //如果某個數和下標不相等,說明這個數沒有出現過
    for(int i = 0; i < nums.size(); i++) {
        if(nums[i] != i + 1)
            return i + 1;
    }
    return nums.size() + 1;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章