找出只出現一次的兩個數字
阿新 • • 發佈:2019-02-24
spa res 方法 () www mes 得出 style 題目
問題
有一個 n 個元素的數組,除了兩個數只出現一次外,其余元素都出現兩次,讓你找出這兩個只出現一次的數分別是幾,要求時間復雜度為 O(n) 且空間復雜度為O(1)(與 n 無關)。
例如:
輸入: [1,2,2,1,3,4]
輸出: [3,4]
解決方法
已知相同的兩個數異或結果為0,在這裏把所有元素都異或,那麽得到的結果就是那兩個只出現一次的元素異或的結果。
然後,因為這兩個只出現一次的元素一定是不相同的,所以這兩個元素的二進制形式肯定至少有某一位是不同的,即一個為 0 ,另一個為 1 ,現在需要找到這一位。
根據異或的性質 任何一個數字異或它自己都等於 0
,所以前面得到這個數字二進制形式中任意一個為 1 的位都是我們要找的那一位。
再然後,以這一位是 1 還是 0 為標準,將數組的 n 個元素分成兩部分。
- 將這一位為 0 的所有元素做異或,得出的數就是只出現一次的數中的一個
- 將這一位為 1 的所有元素做異或,得出的數就是只出現一次的數中的另一個。
這樣就解出題目。忽略尋找不同位的過程,總共遍歷數組三次,時間復雜度為O(n)
代碼:1 #include<cstdio> 2 using namespace std; 3 4 const int maxn = 100000 + 10; 5 int num[maxn]; 6 int n; 78 int main() 9 { 10 scanf("%d", &n); 11 int res = 0; //記錄所有數的異或結果 12 for (int i = 0; i < n; i++) 13 { 14 scanf("%d", &num[i]); 15 res ^= num[i]; 16 } 17 int pos; //記錄“1”的位置 18 for(inti = 0;(1 << i) <= res;i++) 19 if (res & (1 << i)) { pos = i; break; } 20 int ans1 = 0, ans2 = 0; //記錄兩個結果 21 for (int i = 0; i < n; i++) 22 { 23 if (num[i] & (1 << pos)) ans1 ^= num[i]; 24 else ans2 ^= num[i]; 25 } 26 printf("%d %d\n", ans1, ans2); 27 return 0; 28 }
參考鏈接:
1、https://www.zhihu.com/question/269288074/answer/574871689
2、https://www.cnblogs.com/hezhiyao/p/7539024.html
找出只出現一次的兩個數字