LeetCode - 260. Single Number III

在Single Number的基础上,只出现一次的数字从一个变成了两个,同样地我们仍然希望使用xor的技巧来方便地得到两个只出现一次的数字,所以我们需要思考一种方法将给出的数字分为两堆,每堆含有的除了一个只出现一次的数字之外,其他都是出现两次的数字。这样我们就可以在这两堆上分别进行xor得到两个值。

这里我们采用的方法是首先对所有的数字进行xor,得到的值也就是两个只出现一次的数字的xor值,接下来我们寻找得到的结果的二进制从右向左看第一个为1的那一位,根据xor的性质,我们可以知道:两个只出现一次的数字在这一位上是不同的,一个为0,一个为1。所以我们可以根据这一位的不同将数字分为两堆,然后分别进行累计的xor操作。这里有一个小技巧,不需要另外new出两个ArrayList来存储这两堆数字,只要用两个初始值为0的int值,然后分别对它们进行累计xor即可,时间复杂度为O(n),代码如下:

public class Solution {
    public int[] singleNumber(int[] nums) {
        if(nums == null || nums.length == 0){
            return new int[0];
        }
        
        int[] result = new int[2];
        int xor = 0;
        
        for(int i = 0; i < nums.length; i++){
            xor ^= nums[i];
        }
        
        // Find the last digit == 0, and divides nums according to it
        int lastBit = xor - (xor & (xor - 1));
        int group0 = 0;
        int group1 = 0;
        
        for(int i = 0; i < nums.length; i++){
            if((lastBit & nums[i]) != 0){
                group1 ^= nums[i];
            }else{
                group0 ^= nums[i];
            }
        }
        
        // Construct result
        result[0] = group0;
        result[1] = group1;
        return result;
    }
}


知识点:

1. 变量一定要先初始化后再使用,而如果要累计计算^=值的时候,可以把变量初始化为0,因为a ^ 0 = a

2. Java中不可以将非0的int值放到if语句中进行条件判断,需要另外进行逻辑判断得到一个boolean的值,才可以将其用作条件判断

3. number - (number & (number - 1))或者number & (~(number - 1))可以用来得到某个数二进制形式下从右向左看第一个为1的那一位

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值