题目要求:
假设你有一个用1001个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1到1000(包括1000)之间。
此外,除一个数字出现两次外,其他所有数字只出现一次。假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。
解题思路:
数组中的1001个数相互异或的结果与(1-1000)相互异或的结果再做异或,得出的值即位所求
原理:
假设重复数为A,其余999个数相互异或结果为B。
那么1-1000异或结果为A^B;
1001个数异或结果为A^(A^B) 。
由于异或满足交换律和结合律,且X^X = 0, 0^X = X;
则有:A^(A^B) = B ;(A^B)^B=A。
A即为所求。
代码实现:
public static void find(int[] arr, int n){
int result = 0;
for(int i=0 ; i<n+1; i++){
result ^= arr[i]; //数组内的数相互异或
}
for(int i=1 ; i<=n ; i++){
result ^= i; //将上面的结果与1~n的数相互异或
}
System.out.println("找到重复的数为:"+result);
}
public static void main(String[] args){
int[] arr = new int[10001];
for(int i=1;i<=1000;i++){
arr[i] = i;
}
int r = new Random().nextInt(1000);
System.out.println("放入1000以内的一个随机数:"+r);
arr[0] = r;
find(arr,1000);
}
将代码简化为:
public static void find(int[] arr, int n){
int result = 0;
for(int i=0 ; i<n+1; i++){
result ^= arr[i];
result ^= i;
}
System.out.println("找到重复的数为:"+result);
}
输出结果:
第1次试验
放入1000以内的一个随机数:7
找到重复的数为:7
第2次试验
放入1000以内的一个随机数:604
找到重复的数为:604
第3次试验
放入1000以内的一个随机数:667
找到重复的数为:667
第4次试验
放入1000以内的一个随机数:558
找到重复的数为:558
第5次试验
放入1000以内的一个随机数:185
找到重复的数为:185
第6次试验
放入1000以内的一个随机数:933
找到重复的数为:933
第7次试验
放入1000以内的一个随机数:754
找到重复的数为:754
第8次试验
放入1000以内的一个随机数:71
找到重复的数为:71
第9次试验
放入1000以内的一个随机数:390
找到重复的数为:390
第10次试验
放入1000以内的一个随机数:634
找到重复的数为:634