位运算^(异或) (只有1^0或者0^1才等于1,只有不一样的值做^才会等于1)
满足交换律和结合律
A^A=0(1)
A^0=A(2)
有(1)(2)可得A^A^b^c^c=b
连续做异或可以消除重复。
题目:1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?
分析:设重复的数为k
那么1001个数有1,2...k,k...1000
(1,2...k,k,...1000)^(1,2...k...1000)=k
便求出了重复的数k。
代码实现:
(1)先用小数据量做测试,方便检测:
import java.util.Random;
int n=11;//假设有11个数
int []arr=new int[n];
for(int i=0;i<n-1;i++)
arr[i]=i+1;//给arr[0]到arr[9]分别赋值1,2...10
arr[arr.length-1]=new Random().nextInt(n+1)-1;//最后一个数随机生成
for(i=0;i<n;i++)
System.out.println(arr[i]);//输出数组,方便与下面的x1对照,检测是否正确
int x1=0;//定义一个变量,初始化为0,
for(int i=1;i<n;i++)
x1=x1*i;//为了实现1^2^3^...
for(int i=0;i<n;i++)
x1=x1^arr[i];//(1^2^3...^k^...)^(1^2^3^...^k^k^...)结果为k,x1即为所求的重复值k。
System.out.println(x1);
(2)(1)实现无误后,将n换为1001即可,时间复杂度o(n)
import java.util.Random;
public class WeiYiChengDuiDeShu {
public static void main(String args[]) {
int n = 1001;
int[] arr = new int[n];
for(int i=0;i<n;i++)
arr[i]=i+1;
arr[arr.length-1]=new Random().nextInt(n-1)+1;//最后一个数随机生成,范围为1到10的闭区间
for(int i=0;i<n;i++)
System.out.println(arr[i]);
int x1=0;
for(int i=1;i<n;i++)
x1=x1^i;
for(int i=0;i<n;i++)
x1=x1^arr[i];
System.out.println(x1);
}
}
#############################################################################如果可以构建辅助空间的话
int []arr=new int[n];
for(int i=0;i<n;i++)
arr[i]=i+1;
arr[n-1]=new Random().nextInt(n+1)-1;
for(int i=0;i<n;i++)
System.out.println(arr[i]);
int []helper=new int[n];
for(int i=0;i<n;i++)
helper[arr[i]-1]++;//遍历arr[i]例如arr[0]=1 ,减一后为0,则helper[0]=helper[0]+1=1如此以后,除了重复的helper[]为2,其他的helper[]均为一,
for(int i=0;i<n;i++)
if(helper[i]==2)
{System.out.print(arr[i]);
break;