先看一個簡單的,一組數中,只有一個數只出現了奇次,其他所有數都是成對出現的,找出出現奇次數的數。對於這個題,我們只需對所有數及逆行異或即可。理論公式:
a⊕b=b⊕a
a⊕0=a
a⊕b⊕b=a
a⊕(b⊕c)=(a⊕b)⊕c
代碼:
#include <stdio.h> #include <stdlib.h> int main() { int arr[] = { 1, 2, 3, 4, 1, 2, 3 }; int ret = 0; int len = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i < len; i++) { ret ^= arr[i]; } printf("出現奇數次的數爲:> %d\n", ret); system("pause"); return 0; }
現看比較難的,一組數中,只有兩個數只出現了奇次,其他所有數都是成對出現的,找出出現奇次數的數。通過上面的簡單的例子,我們可以知道,只要我們把兩個分開,分爲兩組數,再分別利用異或,就可以得那兩個數。
現在我們看如何將一組數分爲每一組數都只有一個數出現過一次的兩組數:首先我們對所有數進行異或,那麼得到的就是兩個出現奇次的那兩個數的異或,比如{ 1, 2, 3, 4, 1, 2, 7, 3 },就得到7⊕4,這個數肯定不爲0,我們找出這個數的二進制數的最右邊的1(設最右邊的1在第inter位),然後找出數組的每個元素的第inter位,並判斷此位是1還是0,是1的爲一組,是0的爲一組,這樣就分好了組,再利用上面的例子,就可得到出現奇數次的那兩個數。
#include <stdio.h> #include <stdlib.h> int main() { int arr[] = { 1, 2, 3, 4, 1, 2, 7, 3 }; int len = sizeof(arr) / sizeof(arr[0]); int ret = 0; int inter = 0; int retA = 0; int retB = 0; for (int i = 0; i < len; i++) { ret ^= arr[i]; } /*找ret最右邊的1*/ inter = ret - (ret&(ret - 1)); for (int i = 0; i < len; i++) { int a = (arr[i] >> (inter - 1)) % 2; //取出arr[i]的第inter位 if (a == 0) { retA ^= arr[i]; } else { retB ^= arr[i]; } } printf("出現奇數次的兩個數爲:> %d,%d\n", retA, retB); system("pause"); return 0; }