题目:
取值为[1,n-1]含n个元素的整数数组至少存在一个重复数,O(n)时间内找出其中任意一个重复数。如A[]={1,2,2,4,5,4},则2和4均是重复元素。
思想:
(1)如果这n个元素中只含有一个重复的数,那么我们只需要求数组A的和,然后减去这1,2,3...n-1即得到重复的数。
(2)很容易想到排序,但如果是比较排序的想法,时间复杂度会达到O(NlogN);此时我们可以利用数与下标之间的关系来确定,首先明确一点所有的数均小于n;那我们开始从index=0到index=length-1遍历数组,过程如下:
(2.1)若A[index]<n,则temp=A[index],否则temp=A[index]-n。
(2.2)若A[temp]<n,表示数值A[temp]未被访问过,更新A[temp]=A[temp]+n,而A[temp] >= n,表示数值A[temp]已被访问过,直接返回temp。
(3)上述思想归根到底是采用了一种hash冲突的思想,根据所有的数均小于n,来进行处理的;由于只遍历一遍数组,故时间复杂度为O(n),只用到常数个变量,故空间复杂度为O(1)。
程序实现:
#include<stdio.h>
#include<stdlib.h>
int find_number(int *A, int n)
{
int temp;
int index;
for(index = 0; index < n; index++){
if(A[index] < n){
temp = A[index];
}else{
temp = A[index] - n;
}
if(A[temp] < n){
A[temp] += n;
}else{
return temp;
}
}
return -1;
}
int main(void)
{
int A[] = {4,6,7,8,1,7,3,4,4};
int i;
printf("A[]:");
for(i = 0; i < sizeof(A) /sizeof(A[0]) ; i++){
printf("%d ", A[i]);
}
printf("\n");
int a = find_number(A, sizeof(A) /sizeof(A[0]));
printf("search numbers:%d\n", a);
return 0;
}