题目
1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助空间,能否实现。
算法
1.不需要辅助空间
注:因为知道不重复的其他数时哪些所以可以使用此方法,否则只能使用方法二
思路:
只有一个数是出现两次的,联想到 ^
异或运算中,两个相同的数 异或
得到 0, 0
和任何一个数 异或
还等于这个数(即A^A=0,A^0=A)
设题目中的数组为 arr
, 让 arr
与1-1000共1000个数 异或
, 这样除了 arr
中重复了两次那个数得到保留外,其它的数均变为0,输出这个数即可
2.需要辅助空间
使用一个1001个元素的数组helper,helper[i]
记录数字 [i]
出现的次数,helper[i]==2
的 i
即为要找的数
代码如下:
package 位运算;
import jdk.jshell.execution.Util;
import java.util.Random;
import java.util.*;
public class wei {
public static void swap(int [] a,int x,int y)
{
int temp;
temp=a[x];
a[x]=a[y];
a[y]=temp;
}
public static void main(String[] args)
{
int N=1001;
int [] arr=new int[N];
for(int i=0;i<arr.length-1;i++)
{
arr[i]=i+1;
}
//最后一个数是随机数
arr[arr.length-1]=new Random().nextInt(N-1)+1;//nextInt函数作用:该方法的作用是生成一个随机的int值,该值介于[0,n)的区间,随机int值在包含0而不包含n区间内。
//随即下标
int Index=new Random().nextInt(N);
//交换最后一个下标上的数到随机下标位置
swap(arr,Index,arr.length-1);
System.out.println(Arrays.toString(arr));//打印数组的方法
System.out.println("====不建立辅助空间====");
//异或消除重复
int x1=0;
for(int i=1;i<=N-1;i++)
{
x1=(x1^i);//1-1000个数异或
}
for(int i=0;i<N;i++)
{
x1=x1^arr[i];//1-1000个数再与arr中的数异或,得出重复的数
}
System.out.println(x1);
System.out.println("======建立辅助空间的方法=====");
//利用辅助数组的下标代表出现的次数
int[ ] helper=new int[N];
for(int i=0;i<N;i++)
{
helper[arr[i]]++;
}
for(int i=0;i<N;i++)
{
if(helper[i]==2)
{System.out.println(i);
break;}
}
}
}
运行结果: