1. 程式人生 > >找出只出現一次的兩個數字

找出只出現一次的兩個數字

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;
 7
8 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(int
i = 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

找出只出現一次的兩個數字