数组中除了两个数只出现过一次,其他的均出现过两次,请找出这两个只出现过一次的数



如题:数组中除了两个数只出现过一次,其他的均出现过两次,请找出这两个只出现过一次的数

例如:{10,9,8,7,6,6,7,8,9,10,5,5,4,3};

4和3只出现过一次,请找出出现过一次的数。

首先想到的代码应该是上一个提到的遍历两次取出没有找到的相同的数字,代码如下:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public static List findOnlyNum(int[] array){  
  2.     List<Integer> list = new ArrayList<Integer>();  
  3.     for(int i = 0 ;i<array.length;i++){  
  4.         int j = 0;  
  5.         for(;j<=array.length;j++){  
  6.             if(i==j){  
  7.                 continue;  
  8.             }  
  9.             if(j==array.length){  
  10.                 break;  
  11.             }  
  12.             if(array[i]==array[j]){  
  13.                 break;  
  14.             }  
  15.         }  
  16.         if(j==array.length){  
  17.             list.add(array[i]);  
  18.         }  
  19.     }  
  20.     return list;  
  21. }  


那么我们再用上一个提到的高大上的方法在想想有没有更好的解决办法。

上面我们提到运用异或操作得到唯一一次出现的数字,如果我们能将这两个只出现过一次的数字划分开,对划分开的两个序列行进异或,那么就可以等到的我们想要找的两个数。

第一步:我们需要找到一个条件,给这两个出现过一次的数找出可以区分的条件。

相同的数异或等到的结果0,那么整个序列异或的结果就是这两个出现过一次的数的异或。

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public static Integer findOnlyNum1(int[] array){  
  2.     int result = 0;  
  3.     for(int i = 0 ;i<array.length;i++){  
  4.         result^=array[i];  
  5.     }  
  6.     return result;  
  7. }  

第二步:找出他们的不同之处,前面我们讲过,异或按位操作是相同的为0 ,不同的为1,那么这两个数异或的结果转换成2进制时,低位出现第一个1是就可以区分他们了。

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. String binaryResult = Integer.toBinaryString(result);  
[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. int index = binaryResult.length() - (binaryResult.lastIndexOf("1")+1);  

第三步:在index位为1的分为一组,为0的分为一组,将序列划分为两个序列:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. int result1 = 0;  
  2. int result2 = 0;  
  3. for(int i =0;i<array.length;i++){  
  4.     if(((array[i]>>index)&1)==1){  
  5.         result1^= array[i];  
  6.     }else{  
  7.         result2^=array[i];  
  8.     }  
  9. }  

这样就能得出我们想要的结果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值