题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
思路一
代码
public class Find {
public static void main(String[] args){
Find find = new Find();
int[] arr = {2,4,3,6,3,2,5,5};
int[] num1 = new int[1];
int[] num2 = new int[1];
find.FindNumsAppearOnce(arr,num1,num2);
System.out.println(num1[0]);
System.out.println(num2[0]);
}
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null || array.length <= 1){
num1[0] = num2[0] = 0;
return;
}
//整个数组从头两两异或,最终的结果必然是两个不同数字的异或结果
//因为相同的数字两两异或之后为0
//0和任意一个数异或还是这个数本身
int len = array.length;
int sum = 0;
for(int i = 0; i < len; i++){
sum ^= array[i];
}
int index = 0;
//java中int类型占4个字节,即32个bit
//从左开始找到这个异或结果第一个为1的索引(寻找两个特殊数的二进制数的第一个不同的位所在的位置)
while((sum&1) == 0 && index < 32){
sum = sum >> 1;
index++;
}
//以这个索引处是否为1作为判定标准,就将两个不同的数分离开了
//下面就是分两批不停地异或,就会得到这两个不同的数
for(int i = 0; i < len; i++){
//这样就可以分别找到index处为1的独特解以及为0的独特解
if(isBit(array[i],index)){
num1[0] ^= array[i];
}else{
num2[0] ^= array[i];
}
}
}
//判断num的倒数第index位是否为1
private boolean isBit(int num,int index){
//先将num向右移index位
num = num >> index;
//判断倒数第index位是否为1
if((num & 1) == 1){
return true;
}else{
return false;
}
}
}
思路二
利用hashset的不可重复性
import java.util.HashSet;
public class Finde {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashSet<Integer> set = new HashSet<Integer>();
for (int i = 0;i < array.length;i++){
/**
* Adds the specified element to this set if it is not already present.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*/
boolean flg = set.add(array[i]);
if(!flg){
//如果set中已经存在,说明该数字出现了两次那么就删除该数字
set.remove(array[i]);
}
}
Object[] temp =set.toArray();
num1[0] = (int) temp[0];
num2[0] = (int) temp[1];
}
}