1. 程式人生 > >劍指offer:找到陣列中重複的值

劍指offer:找到陣列中重複的值

題目:在一個長度為n的數組裡的所有數字都在0~n-1的範圍內。陣列中某些數字是重複的,但是不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出陣列中任意一個重複的數字。例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是重複的數字2或者3.

分析:因為這個陣列的長度是n並存放了n個數字,如果這個陣列的數字沒有重複,那麼排序之後,它的數字和陣列下標應該是一一對應的。那麼由於陣列中存在重複的數字,就會有些數字的下標沒有對應的數字,而是對應其他數字。

具體怎麼做?首先我們可以重排這個陣列,假設該陣列為a。從頭開始,當掃描到下標為i的數字時,此時這個位置存放的值我們設為m。如果i=m,則跳到下標為i+1的數字;如果i≠m,則比較m與a[m]的值。如果m=a[m],那麼我們就找到了重複的值了,如果不相等,則將m放到a[m]處,而a[m]放到a[i]處。接下來就是重複這個過程了。

我們以上面的a[7]={2,3,1,0,2,5,3}為例分析。

a[7]={2,3,1,0,2,5,3},a[0]=2,0≠2->a[2]=[1],2≠1=》a[7]={1,3,2,0,2,5,3};

a[7]={1,3,2,0,2,5,3},a[0]=1,0≠1->a[1]=[3],1≠3=》a[7]={3,1,2,0,2,5,3};

a[7]={3,1,2,0,2,5,3},a[0]=3,0≠3->a[3]=[0],3≠0=》a[7]={0,1,2,3,2,5,3};

接下來會一直到a[4];

a[7]={0,1,2,3,2,5,3},a[4]=2,4≠2->a[2]=2,這個時候就找到了重複的值了,搞定!

程式碼示例如下:

#include<stdio.h>

int duplicate(int numbers[],int length){
	int i,temp,duplicate;
	if(numbers == NULL || length <= 0)
		return -1;
	for(i = 0; i < length; ++i){
		if(numbers[i] < 0 || numbers[i] > length - 1)
			return -1;
	}

	for(i = 0; i < length; ++i){
		while(numbers[i] != i){
			if(numbers[i] == numbers[numbers[i]]){
				duplicate = numbers[i];
				return duplicate;
			}
			temp = numbers[i];
			numbers[i] = numbers[temp];
			numbers[temp] = temp;
		}
	}
	return -1;
}

int main(){
	int a[7] = {2,3,1,0,2,5,3};
	int length,i;

	length = sizeof(a)/sizeof(int);
	for(i = 0; i < length; i++)
		printf("%d ",a[i]);
	printf("\n");

	printf("%d\n", duplicate(a,7));

	for(i = 0; i < length; i++)
		printf("%d ",a[i]);
	printf("\n");

	return 0;
}