如题:数组中除了两个数只出现过一次,其他的均出现过两次,请找出这两个只出现过一次的数
例如:{10,9,8,7,6,6,7,8,9,10,5,5,4,3};
4和3只出现过一次,请找出出现过一次的数。
首先想到的代码应该是上一个提到的遍历两次取出没有找到的相同的数字,代码如下:
public static List findOnlyNum(int[] array){
List<Integer> list = new ArrayList<Integer>();
for(int i = 0 ;i<array.length;i++){
int j = 0;
for(;j<=array.length;j++){
if(i==j){
continue;
}
if(j==array.length){
break;
}
if(array[i]==array[j]){
break;
}
}
if(j==array.length){
list.add(array[i]);
}
}
return list;
}
那么我们再用上一个提到的高大上的方法在想想有没有更好的解决办法。
上面我们提到运用异或操作得到唯一一次出现的数字,如果我们能将这两个只出现过一次的数字划分开,对划分开的两个序列行进异或,那么就可以等到的我们想要找的两个数。
第一步:我们需要找到一个条件,给这两个出现过一次的数找出可以区分的条件。
相同的数异或等到的结果0,那么整个序列异或的结果就是这两个出现过一次的数的异或。
public static Integer findOnlyNum1(int[] array){
int result = 0;
for(int i = 0 ;i<array.length;i++){
result^=array[i];
}
return result;
}
第二步:找出他们的不同之处,前面我们讲过,异或按位操作是相同的为0 ,不同的为1,那么这两个数异或的结果转换成2进制时,低位出现第一个1是就可以区分他们了。
String binaryResult = Integer.toBinaryString(result);
int index = binaryResult.length() - (binaryResult.lastIndexOf("1")+1);
第三步:在index位为1的分为一组,为0的分为一组,将序列划分为两个序列:
int result1 = 0;
int result2 = 0;
for(int i =0;i<array.length;i++){
if(((array[i]>>index)&1)==1){
result1^= array[i];
}else{
result2^=array[i];
}
}
这样就能得出我们想要的结果了。