找到一個數組中只出現一次的數
阿新 • • 發佈:2018-12-26
你有沒有遇到這樣的題,在一個數組中,只有1個數字出現一次,其他的數字都出現了兩次,那麼你能找到這個只出現一次的數字麼?
這只是簡單的1.0版本,還有如果在這個陣列中,有兩個數字出現了一次,其他的數字都出現了兩次,那麼你能找到這兩個數字麼?
還有2.0版本,三個數字出現一次呢?四個呢?五個呢?你要怎麼去實現呢?
首先,我們一步一步來,從找一個數字開始,其實,如果不是考慮到記憶體的關係,用桶排序是可以很好地解決這個問題的,但是,桶排序,實在是太耗記憶體了。那麼我們就換個思路,我們想到,在運算子中有這樣一個^(異或)的符號,我們完全可以利用這個異或來實現。也許你已經想到要怎麼去實現了,沒錯,就是這樣實現的。舉個例子吧,a[3] = {1,1,2},將這三個數異或一下,就可以得到2,是不是很簡單?這樣我們就找到了這個只出現一次的數字了。好,那我們用程式碼來實現吧:
#include<stdio.h>
int main()
{
int a[] = {1,1,2,2,3,3,4,4,5};
int sz = sizeof(a)/sizeof(a[0]);
int i = 0;
int x = 0;
for(i=0;i<sz;i++)
{
x ^= a[i];//將所有的數與一下
}
printf("%d\n",x);
return 0;
}
你也可以自己實現一下。
那麼我們接下來來看兩個數字均出現一次的情況吧。其實如果我們這麼想,如果可以把這個陣列分成兩組,把這兩個數字分別分到兩組中去,實際上就是找一個數字了。
我們可以來看一下,如果直接將所有的數字異或在一起,得到的是什麼呢?舉個例子a[]={1,1,2,2,3,3,4,5},
以這個例子來看,應該是 4^5(4和5異或的結果),那我們從二進位制數的角度來看一下
100//4
101//5
001//異或之後的結果
那麼我們可以看到,4和5的二進位制數有一位不同,我們可不可以依據這個來進行分組呢?
那麼,分組的結果是:
第一組:1,1,3,3,5 ;
第二組: 2,2,4;
在這兩組中分別運用第一種方法,即可分別找到這兩個數字了。
怎麼實現呢?
#include<stdio.h> int main() { int a[] = {1,1,2,2,3,3,4,4,5,5,6,7}; int i = 0; int sz = sizeof(a)/sizeof(a[0]); int n = 0; int pos = 0; int x = 0; int y = 0; for(i=0;i<sz;i++) { n ^= a[i];//將所有的數異或 得到 6^7 的結果 } for(i=0;i<32;i++) { if(1 == (n>>i)&1) { pos = i;//找到 6^7 的二進位制數中為1的一位 break; } } for(i=0;i<sz;i++)//開始分組 { if(1 == ((a[i]>>pos)&1)) { x ^= a[i];//得到一個數 } else { y ^= a[i];//得到另一個數 } } printf("%d %d\n",x,y); return 0; }
你會了麼?
3.0版呢以後再更新。