一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
//     public int[] FindNumsAppearOnce (int[] array) {
//         // write code here
//         //找出重复数字呀,找出不重复的,最快的就是hash
//         HashSet<Integer> set =new HashSet<>();
//         int index= 0;
//         for(index=0;index<array.length;index++){
//             if(!set.add(array[index])){
//               set.remove(array[index]);
//             }
//         }
//         int[] result = new int[set.size()];
//         index = 0;
//         Iterator<Integer> iterator = set.iterator();
//         while(iterator.hasNext()){
//             result[index++]=iterator.next();
//         }
//         return result;
//     }
    //异或处理  相同数异或为0,0异或 1个数还是这个数  所有数直接异或就能找到唯一不重复的数了。
    //寻找两个不重复的数
      public int[] FindNumsAppearOnce (int[] array) {
          int[] result= new int[2];
          int m = 0;
          for(int num :array){
              m ^= num;
          }
          //找到两个数  不同的那一位
          int x= 1;
          while((m&x) == 0){
              x<<=1;
          }
           for(int num :array){
               //在x 这位 两个数不同,所以  这位与上x 为0的为一组,不为0 的  另一组
             if((num & x) == 0){
                 result[0] ^=num;
             }else{
                 result[1] ^=num;
             }
          }
          if(result[0]>result[1]){
              m = result[0];
              result[0] = result[1];
              result[1] = m;
          }
          return result;
          
    }
}

本文给出两种方法

一个是哈希,时间复杂度o(n) 空间复杂度o(n)

一个是位运算的方法 时间复杂度o(n) 空间复杂度o(1)

位运算的逻辑就是利用异或的性质,只有 0 ^1 = 1 其他为0.所以相同数字 异或是0,不同数字异或是所有相同位置 不同数字 的值。

知道了这个性质,难点就在于如何区别开 两个都不重复的数字,怎么能够单独找到其中一个!!!

遍历一次数组,异或后得到一个数,这个数就是不重复的两个数异或出来的结果,这两个数字不同点就在于有一些位置的数字是不同的,已经通过 异或运算找到了这些位置,这些位置的数字就是1.

但是如何用数字表示呢?

可以通过与运算,其实就相当于比如 快速幂这种思想,求一个数 有几个1。每一位的数字都去& 1

如果结果是1,说明这个数的这一位就是1.否则就是0。 num&1 == 0,如果等于0,就把1向左移一位,去比较num数字的第二位,循环遍历num的每一位,直到找到num为1的那一位就是两个数不同的那一位。记为x, 第一位不同 x=1,第二位不同 x=10

在遍历一次array,先不去管重复的元素,如果 因为两个单独数字在x这一位,一个是0,一个是1,所以 数字& x==0    说明 是其中一个元素,否则是另一个。这样就可以把数组分成两组。各自运算,重复元素没有影响,因为元素重复的 &x ==0 的情况下,所有重复元素都在同一组中,异或后为0,消失不见

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值