1. 程式人生 > >41. first-missing-positive

41. first-missing-positive

      這道題呢技巧性比較強,對於像我這樣的新手第一次一般是想不出來這種方法的。

      題目的大意是找出一個int陣列中第一個缺失的正整數,比如:0,1,3,5. 這組int陣列中,第一個缺失的正整數是2,當然最直觀的思路是我從1到n一個一個到陣列中去尋找,看第一個缺失的誰,這樣複雜度是O(N^2),而這種思路程式碼比較簡單,另一種比較新穎的思路是利用下標和正整數之間的關係,來完成尋找,最終是O(n)的複雜度。

      利用正整數與下標之間的關係,假設如果現在的數組裡有4個數,分別是1,2,4,5,那麼,如果他們按照順序排列起來我們就可以直接從頭到尾掃一遍,通過比較nums[i] 和 下標i的關係,就知道哪個正數缺失,當第一次出現nums[i] != i+1時,就說明i+1是第一個缺失的正整數。

       剛剛提到了排序,其實該題中,我們並不需要將所有的元素排一下,而是需要將對應的元素放入對應的位置上去,即使得符合條件的數字滿足nums[i] == i+1;

       整個陣列分為兩種情況,第一種是1 2 3 4 6,這樣在第四位上會出現nums[i] != i+1的情況,返回的第一個缺失正數為 i+1即可,另外一種是  1 2 3 4 5,這樣,陣列中每一位都是符合nums[i] == i+1,所以第一個缺失的正整數應該是i+2;

基於以上的思想以下是程式碼:

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        if (nums.size() < 1) {
            return 1;
        }
        
        for (int i=0; i<nums.size();) {
            if (nums[i]>0 && nums[i]<=nums.size() && nums[i]!=i+1 && nums[i]!=nums[nums[i]-1]) {
                swap(nums[i], nums[nums[i]-1]);
            } else {
                ++i;
            }
        }
        
        for (int i=0; i<nums.size(); ++i) {
            if (nums[i] != i+1) {
                return i+1;
            } else if (i == nums.size()-1) {
                return i+2;
            }
        }
        return 0;
    }
};