利用位运算找到数组中只出现一次的数字

题目描述

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

num1,num2分别为长度为1的数组。传出参数
将num1[0],num2[0]设置为返回结果

方法一、遍历所有元素,将出现一次的元素保存到集合里。
首先查看集合中是否包含当前元素,如果包含说明这个元素出现了两次,则把它删除,如果不包含则将这个元素添加到集合中。

public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        ArrayList<Integer> list = new ArrayList<>();
        for(int i=0;i<array.length;i++){
            if(list.contains(array[i])){
                for (int i1=0;i1<list.size();i1++){
                    if(list.get(i1)==array[i]){
                        list.remove(i1);
                    }
                }
            }
            else
                list.add(array[i]);
        }
        num1[0] = list.get(0);
        num2[0] = list.get(1);
    }

方法二、运用异或运算。
思路:
(1)题中给出了一个数组除了两个数字之外,其他的数字都出现了两次。则可以联想到两个相同的数的异或的结果为0,而任何数异或0则还是这个数。
(2)依照这个思路,我们可以将所有数依次进行异或,最后得到的数一定是两个出现一次的数的异或后的结果,将他记录为result。
(3)接下来就是通过这个异或后的结果找到两个数。根据异或运算的特点可知,result的二进制形式为1的位,就是两个出现一次的数中不同的位.
以下举个例子理解这句话
在这里插入图片描述
51^42 结果为011001=25。这样为了区分51和42就可以找到011001的第一个1所在的位,即第一位,51为1,42为0。
(4)知道了区分条件,那么就可以将原数组分为两组。相同的数肯定在一个组,因为相同数字所有位都相同,而不同的数,肯定不在一组。分组标准是由第三步确定。如此,然后把这两个组按照最开始的思路,依次异或,剩余的两个结果就是这两个只出现一次的数字。
具体代码如下

public void FindNumsAppearOnce(int[] array, int[] num1, int[] num2)    {
        int length = array.length;
        if(length == 2){     //只有两个元素的时候
            num1[0] = array[0];
            num2[0] = array[1];
            return;
        }
        int Result = 0;
        for(int i = 0; i < length; ++i){
            Result ^= array[i];
        }            //Result得到的结果为1的位是两个只出现一次的数的不同位
        int index = findFirst1(Result);   //找到第一个1,也就是第一个不同的位
        for(int i = 0; i < length; ++i){
            if(isBit1(array[i], index)){     //确定当前为哪一组
                num1[0] ^= array[i];
            }else{
                num2[0] ^= array[i];
            }
        }
    }

    private int findFirst1(int bitResult){
        int index = 0;
        while(((bitResult & 1) == 0) && index < 32){
            bitResult >>= 1;
            index++;
        }
        return index;
    }

    private boolean isBit1(int target, int index){
        return ((target >> index) & 1) == 1;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值