1. 程式人生 > >LeetCode演算法題-Missing Number(Java實現-四種解法)

LeetCode演算法題-Missing Number(Java實現-四種解法)

這是悅樂書的第200次更新,第209篇原創

01 看題和準備

今天介紹的是LeetCode演算法題中Easy級別的第65題(順位題號是268)。給定一個包含n個不同數字的陣列,取自0,1,2,...,n,找到陣列中缺少的數字。例如:

輸入:[3,0,1]
輸出:2

輸入:[9,6,4,2,3,5,7,0,1]
輸出:8

注意:您的演算法應該以線性執行時複雜性執行。 你能用恆定的額外空間複雜度來實現嗎?

本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。

02 第一種解法

特殊情況:當nums為null的時候,或者nums中沒有元素的時候,直接返回0即可。

正常情況:缺失的數字分為三種情況:一是缺失的數字在中間,比如{0,1,2,4},此時缺失的數字是3;二是缺失的數字在末尾,比如{0,1,2,3},此時缺失的數字就是4;三是缺失的數字在頭部,比如{1,2,3,4},此時缺失的數字就是0。

先將陣列從小到大排序,然後使用for迴圈,判斷索引是否相等,不相等就是中間缺失的那個數,如果中間不缺數,最後返回索引即可,因為已經在迴圈體中自加1,最後返回的時候不用再加1。

此解法時間複雜度是O(nlog(n)),空間複雜度是O(1)

public int missingNumber(int[] nums) {
    if (nums == null || nums.length < 1) {
        return 0;
    }
    Arrays.sort(nums);
    int index;
    for (index = 0; index < nums.length; index++) {
        if (index != nums[index]) {
            return index;
        }
    }
    return index;
}


03 第二種解法

通過觀察,我們可以發現,nums中的元素組成是一個以1為等差的等差數列,我們可以通過等差數列的和來找出缺失的元素,其求和公式為:

Sum = n*(A1+An)/2

題目中的陣列是從0開始到n,即A1=0,An=n-1,我們計算的時候可以從1到陣列長度,即A1=1,An=n,然後對其求和,藉助for迴圈,此處有兩種方式,一是用和去減每一個元素,最後剩下的就是缺失的元素;二是算出陣列所有元素的和,再算等差數列的和與其的差值,就是缺失的元素。

此解法的時間複雜度是O(n),空間複雜度是O(1)

public int missingNumber2(int[] nums) {
    if (nums == null || nums.length < 1) {
        return 0;
    }
    int sum = (nums.length*(1+nums.length))/2;
    for (int n : nums) {
        sum -= n;
    }
    return sum;
}


04 第三種解法

藉助位運算中的異或(^)運算,通過一個運算公式:a^b^b = a,我們可以算出缺失的那個數字。例如:

陣列nums={0,1,2,4},陣列的索引是{0,1,2,3}

missing=4^(0^0)^(1^1)^(2^2)^(4^3)

       =3^(0^0)^(1^1)^(2^2)^(4^4)

       =3

其中最開始的4就是陣列的長度。

此解法的時間複雜度是O(n),空間複雜度是O(1)

public int missingNumber3(int[] nums) {
    if (nums == null || nums.length < 1) {
        return 0;
    }
    int xor = nums.length;
    for (int i = 0; i < nums.length; i ++) {
        xor = xor ^ nums[i] ^ i;
    }
    return xor;
}


05 第四種解法

使用HashSet,先將陣列中的每一個元素存入其中,然後利用for迴圈,從0到n,判斷set中是否包含當前索引,不包含的就是缺失的那個數。

此解法也可以用HashMap做,思路都是一樣的,時間複雜度是O(n),空間複雜度是O(n)

public int missingNumber4(int[] nums) {
    if (nums == null || nums.length < 1) {
        return 0;
    }
    Set<Integer> set = new HashSet<>();
    for (int num : nums) {
        set.add(num);
    }
    for (int i=0; i<=nums.length; i++) {
        if (!set.contains(i)) {
            return i;
        }
    }
    return -1;
}


06 小結

演算法專題目前已連續日更超過一個月,演算法題文章65+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。

以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!