leetcode 只出现一次的数字 III

题目链接
思路:异或+分类
这个题目是只出现一次的数字,但是有两个只出现一次的数字。
先从简单一点的题目出发,如果只有一个出现一次的数字,方法是只要全部异或一遍,得到的就是答案。
现在有两个数字,全部异或一遍,得到的数字是两个答案异或的结果。
那么我们需要将这个问题简化一下,能不能把这个数组分为两个数组,并且要将这两个答案分到不同的数组中。
这才是问题的核心
我们想想这两个答案有什么不同的特征呢,异或一定不为0。
这就是突破点,异或一定不为0,那么二进制表示一定存在至少一位不相同。
那么我们就可以找到某一个这两个答案二进制不同的位,进行分类,那么就可以保证这两个答案一定被分在不同的数组,理论存在,开始代码。
代码:

class Solution {
    public int[] singleNumber(int[] nums) {
        int sum = 0;//记录两个答案异或的结果
        for(int i = 0; i<nums.length;i++){
            sum ^= nums[i];
        } 
        //记录两个答案第q位不同
        int q = 0;
        
        while( (sum  & 1 )==0){
            q++;
            sum >>= 1;
        }
        
        //两个答案在第q位不同,肯定是一个为1,一个为0
        //res1表示第q位为1的,res0表示第q位为0的 
        int res1 = 0;
        int res0 = 0;
        //循环异或,这里是分组的异或
        for(int i = 0;i < nums.length;i++){

            if( (( (nums[i]>>q) ^ sum) &1) ==0 ){
               	//第q位为0的一组进行异或
                res0 ^= nums[i];
            }else{
            	//第q位为1的一组进行异或
                res1 ^= nums[i];
            }
        }
        return new int[]{res1,res0};
    }
}

这里再记录一下另一种查找二进制低位第一个不相同的位的方法

class Solution {
    public int[] singleNumber(int[] nums) {
        int sum = 0;
        for(int i = 0; i<nums.length;i++){
            sum ^= nums[i];
        } 
        // sum & -sum 得到的这个数的1出现在哪,那么就是哪个位不同     
        sum = sum == Integer.MIN_VALUE ? sum : (sum & -sum);
        int res1 = 0;
        int res0 = 0;
        for(int i = 0;i < nums.length;i++){
            if( (nums[i]&sum) ==0 ){
                res0 ^= nums[i];
            }else{
                res1 ^= nums[i];
            }
        }
        return new int[]{res1,res0};
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值