找出1~1000中的重复数字,其中只有一个是重复的
题目
找出1~1000中的重复数字,其中只有一个是重复的
思路
方法1:HashMap实现
遍历数组把每个数存入到HashMap中ifMap不存在就存入else直接跳出循环时间复杂度为O(N)遍历数组空间复杂度为O(N).
下面就看代码实现:
public static int getDuplicateNum(int[] arr){
if (arr.length==0) return -1;
HashMap<Integer,Integer> map=new HashMap<>();
int res=0;
for (int i = 0; i <arr.length ; i++) {
if (!map.containsKey(arr[i])){
map.put(arr[i],i);
}else {
res=arr[i];
break;
}
}
return res;
}
能不能不申请额外的空间呢?
方法2:累加求和法
求出0~1000的和和遍历数组求和之后相减即可求出重复的数字
下面就看代码实现:
public static int getDuplicateNum(int[] arr){
if (arr.length==0) return -1;
int sum=0,arrsum=0;
for (int j=0;j<1000;j++){
sum+=j;
}
for (int i = 0; i <arr.length ; i++) {
arrsum+=arr[i];
}
return arrsum-sum;
}
此方法有缺陷就是如果数组的和超出了int的范围就不适合了有没有更适合的方法呢?
方法3:或异法
因为1^1=0所有我们想到了或异法求解第一步先遍历0~1000的数然后用或异求和然后遍历数组同样或异求和
举个例子以**{1,3,4,2,5,3}数组为例(134253)(12345)=3**即3为重复的数字
public static int getDuplicateNum(int[] arr){
if (arr.length==0) return -1;
int result=0;
for (int i = 0; i <arr.length ; i++) {
result ^=arr[i];
}
for (int i = 1; i <arr.length ; i++) {
result ^=i;
}
return result;
}
测试代码:
public static void main(String[] args) {
int[] arr=new int[1001];
for (int i = 0; i <1000 ; i++) {
arr[i]=i;
}
arr[1000]=6;
int num = getDuplicateNum(arr);
System.out.println("重复数字为:"+num);
int num1 = getDuplicateNum2(new int[]{1,2,3,4,5,6,7,3});
System.out.println("重复数字为:"+num1);
int num2 = getDuplicateNum1(arr);
System.out.println("重复数字为:"+num2);
}
Files\Java\jdk1.8.0_74\jre\lib\rt.jar;E:\workspace\JavaAlgorithmInterview\out\production\JavaAlgorithmInterview"
重复数字为:6
重复数字为:3
重复数字为:6