- 问题描述
给定一个数组,除了其中两个元素出现一次外,其余元素均出现了两次,找出只出现一次的两个元素 - 解决方案
方案1:利用集合,遍历数组,若集合中存在该元素,则删除,若不存在,则添加进去,最后集合中就只包含这两个元素了。
方案2:比较巧妙,对于数组中所有的元素进行异或,可以得到一个非零结果。该 非零结果即是要寻找的两个元素异或的结果,该结果中的从最低位起第一位不为0的位,必定是因为要寻找的两个数在该位一个是0,一个是1,异或之后才出现1。因此以该结果中从最低位起第一位不为0的位的0或1为筛选条件,再次异或遍历该数组,即可筛选出这两个元素,问题解决
/**
* 给定一个数组,其中有两个数只出现一次,其余均出现两次,找出这两个数
* @param arr
* @return
*/
//方案1:集合方法解决
public static int[] FindNumsAppearOnce(int[] arr){
int[] res = new int[2];
HashSet set = new HashSet();
for (int i = 0; i < arr.length; i++) {
if(set.contains(arr[i]))
set.remove(arr[i]);
else
set.add(arr[i]);
}
int i = 0;
for (Object o:set) {
res[i ++] = (int)o;
}
return res;
}
//方案2:位运算方法解决
public static int[] FindNumsAppearOnce2(int[] arr){
int[] res = new int[2];
int temp = 0;
for (int i = 0; i < arr.length; i++) {
temp = temp ^ arr[i];
}
int count = 0;
while((temp & (1<<count)) == 0){
count ++;
}
for (int i = 0; i < arr.length; i++) {
if((arr[i] & (1 << count)) == 0){
res[0] = res[0] ^ arr[i];
}
else{
res[1] = res[1] ^ arr[i];
}
}
return res;
}