【LeetCode】41. First Missing Positive 找到第一個未提到的正整數

一、概述

輸入一個數組,其元素均爲整數,輸出最小的未在數組中出現的整數。要求時間複雜度O(n),空間複雜度O(1)。

一看時間複雜度O(n),沒法排序做了,倒也是,這能排序做就不是hard題了。第一反應哈希,開了65536的數組,結果一個測試樣例是int的最大值,直接就把哈希爆了。想不出什麼好方法來做。只好去討論區看。這羣人可是真的牛逼。

二、分析

不得不說很久沒做題之後敏感性都差了很多,一看時間複雜度n空間複雜度1第一反映應該就是在原數組上動刀,遍歷數遍。

這題和之前PAT上的一道題差不多,關鍵在於排序。

其具體思路如下:

對於一個輸入數組,例如“35128697”,最終排出來的應該是“12395678”,然後發現本來是4的地方應該是9,就找出了缺失的4。

那麼現在的問題就是。找這個4要排序,但是最牛逼的算法也只能是nlogn,不符合要求,怎麼辦?

那我們來看一下,普通的排序算法,時間話費爲nlogn是爲什麼:是因爲每個元素都要花費logn的時間去找到它自己的位置。但是我們需要所有元素的位置麼?比如輸入n個元素,我們最多需要知道最大元素爲n的位置,n+1都不需要,就能夠找出想要的答案。那麼問題就轉換成部分元素排序。怎麼排?交換位置。如下圖:

首先看位置1,位置1處爲3,實際上是在數組的第0號元素,但爲了表述方便,我們稱之爲位置1,由於位置1處不爲1,因此將3與位置3的元素互換,從而位置1爲1,位置3爲3;

然後往下移動,位置2處爲5,從而位置2與位置5處的元素互換,位置2處元素變爲8;

然後位置2與位置8互換,位置2處元素變爲7;

然後位置2與位置7互換,位置2處變爲9;

位置2沒法與位置9互換,因爲沒有位置9,繼續往下;

位置3處爲3,繼續往下;

位置4處爲2,位置4與位置2互換,位置4變爲9,往下;

位置5、6、7、8均正確,不換了。

然後從頭遍歷,發現位置4處元素不對,返回4。

觀察整個循環,我們可以得出,swap最多進行n次,因爲swap每進行一次,就有一個元素回到正確位置,而我們最多需要n個正確位置的元素,因此時間複雜度爲O(n)。

代碼如下:

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        for(int i=0;i<nums.size();i++)
        {
            while(nums[i]>0&&nums[i]<=nums.size()&&nums[nums[i]-1]!=nums[i])
                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;
    }
};

三、總結

你問我學到了啥?

我只能說我學到了在只求前n個元素有序時候的O(n)寫法,這種把問題轉化的能力太難學了,是天資。

如何能夠從“找第一個未出現的元素”轉換到“令前n個元素有序”,這個思想太難了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章