劍指offer:找到陣列中重複的值
阿新 • • 發佈:2018-12-11
題目:在一個長度為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; }