1. 程式人生 > >找到一個數組中只出現一次的數

找到一個數組中只出現一次的數

你有沒有遇到這樣的題,在一個數組中,只有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版呢以後再更新。