問題描述:
給定一個包含 0, 1, 2, ..., n
中 n 個數的序列,找出 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)