上级目录:算法很美
1. 题目
一个数组里除了某一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。
2. 异或思路
异或的运算是A ^ A=0,也就是说偶数个相同的元素异或,结果肯定是0。A ^ A ^ A =A,也就是说奇数个相同元素异或,结果是A本身。
那么根据上面的思路,我们可以设数组中出现两次的元素为A组元素,一次的为B组元素,那么数组中所有元素异或之后,最后只剩下B组元素,也就是需要求的那个数字。
- 异或代码:
package com.example.algorithm.demo.c2;
/**
* 找出落单的数
*/
public class c13 {
public static void main(String[]args){
//设计一个符合条件的数组, 即A+B=N,N为奇数,A为偶数,B=1为奇数,A=N-B
int N = 11;
//新建数组
int[] arr = new int[N];
//对数组中的A元素按照偶数条件进行填充
for(int i = 0; i < (N/2); i ++){
arr[i] = i; arr[N-i-1] =i;
}
//填充B元素
arr[N/2] = N/2;
//进行异或运算
int x1 = 0;
for (int i = 0; i < arr.length; i ++){
x1 = (x1^arr[i]);
}
System.out.println("异或B:"+x1);
}
}
3. 暴力破解法(使用辅助空间)
假设数组arr符合条件,我们设计另外一个数组helper对arr进行遍历每次循环对helper[arr[i]]做加一操作,那么最终下标是A组元素的helper数组的值是2,B组元素的helper数组的值是1,所以只需要再次进行循环,找出helper数组值为1 的下标,并且把他输出即可
- 暴力破解代码
package com.example.algorithm.demo.c2;
/**
* 找出落单的数
*/
public class c13 {
public static void main(String[]args){
//设计一个符合条件的数组, 即A+B=N,N为奇数,A为偶数,B=1为奇数,A=N-B
int N = 11;
//新建数组
int[] arr = new int[N];
//对数组中的A元素按照偶数条件进行填充
for(int i = 0; i < (N/2); i ++){
arr[i] = i; arr[N-i-1] =i;
}
//填充B元素
arr[N/2] = N/2;
System.out.println("=============异或破解==========");
//进行异或运算
int x1 = 0;
for (int i = 0; i < arr.length; i ++){
x1 = (x1^arr[i]);
}
System.out.println("异或B:"+x1);
System.out.println("=============暴力破解==========");
//辅助数组helper,去重之后数组长度为A/2+B=(N-1)/2+1=(N+1)/2,因为N是奇数所以数组长度最终为N/2+1
int [] helper = new int[N/2+1];
//遍历下标为arr[i]的helper数组
for (int i = 0; i < arr.length; i ++){
helper[arr[i]]++;
}
//得到B
for (int i =0; i< helper.length; i ++){
if (helper[i] == 1){
System.out.println("暴力B:"+i);
break;
}
}
}
}