LeetCode算法入門 缺失數字 解法與分析

問題描述:

給定一個包含 0, 1, 2, ..., nn 個數的序列,找出 0 … n 中沒有出現在序列中的那個數。

示例 1:

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

示例 2:

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

說明:
你的算法應具有線性時間複雜度。你能否僅使用額外常數空間來實現?

解法一:

用排序,然後找哪個數字不在。

思路:此題只需要採用位運算,每次將原來的數字向左移動1位,就需要把該末尾加到我們的數字中去即可,此題需要注意的是一點要循環32次,不僅是有32位,最重要的不能判斷到原來的數字爲0就結束循環,這樣就有可能的導致沒有補足0所以要循環32次。

同時對於左移而言,末尾全部補上的是0,而對於右移而言左邊補的是原本最高位的數字,比如一個32位的數字最高位(也就是符號位)爲1就全部補上1,如果爲0 就全部補上0.這個知識點也是面試常考的。

時間複雜度是O(nlogn).

解法二:

哈希表。遍歷數組,每個數是否出現一次。

但是空間複雜度是O(n).

解法三:

數學方法,0~n的和可以用高斯公式n(n+1)/2,所以減一下就知道是缺少哪個數字了。

代碼如下:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int n = nums.size();
        int sum = n*(n+1)/2;
        int sum_now = 0;
        for(int i = 0; i < n;i++){
            sum_now += nums[i];
        }
        return sum - sum_now;
    }
};

解法四:

看力扣官方的解法,沒太看懂。

分析

由於異或運算(XOR)滿足結合律,並且對一個數進行兩次完全相同的異或運算會得到原來的數,因此我們可以通過異或運算找到缺失的數字。

算法

我們知道數組中有 nn 個數,並且缺失的數在 [0…n][0…n] 中。因此我們可以先得到 [0…n][0…n] 的異或值,再將結果對數組中的每一個數進行一次異或運算。未缺失的數在 [0…n][0…n] 和數組中各出現一次,因此異或後得到 0。而缺失的數字只在 [0…n][0…n] 中出現了一次,在數組中沒有出現,因此最終的異或結果即爲這個缺失的數字。

在編寫代碼時,由於 [0…n][0…n] 恰好是這個數組的下標加上 nn,因此可以用一次循環完成所有的異或運算,例如下面這個例子:

下標 0 1 2 3
數字 0 1 3 4
可以將結果的初始值設爲 nn,再對數組中的每一個數以及它的下標進行一個異或運算,即:

下標 0 1 2 3
數字 0 1 3 4

​ 可以將結果的初始值設爲 n,再對數組中的每一個數以及它的下標進行一個異或運算,即:

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

代碼如下:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int missing = nums.size();
        for (int i = 0; i < nums.size(); i++) {
            missing ^= i ^ nums[i];
        }
        return missing;
    }
};

作者:LeetCode
鏈接:https://leetcode-cn.com/problems/missing-number/solution/que-shi-shu-zi-by-leetcode/
來源:力扣(LeetCode)

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