最近学了下位运算,简单说说收获吧。
首先我们要了解下常见的位运算操作:
- 与或非操作

 - 异或操作

 
进阶规律:与或非 和 异或都是满足结合律的。
 
 
//重点
a&b&c=ab(b|c)
a^a=0
a^(~a)=1
0^b=b
 
我们先来看看第一道题:

做这道题需要一个重要的知识点:
a^b^a=a^a^b=0^b=b
 
也就是说一堆数一起异或,最后剩下的应该是非偶数重复数的异或和。
上面的问题重复的数都是偶数,就一个不重复的数。我们将它异或,结果就是我们要的数。
代码如下:
class Solution {
    public int singleNumber(int[] nums) {
     int ans =0;
     //求所有数的异或和
    for(int i=0;i<nums.length;i++){
        ans ^=nums[i];
    }
    return ans;
    }
}
 
第二道题 :数组不重复的数字有两个,我们把它挑出来。

 这道题就比上个题难了一些。
 需要用到两个套路。
 我们拿 [2,2,3,5]举例子:
 我们将数组里的数字异或操作,观察下这个异或值的二进制形式。
0000 0000 0000 0011
0000 0000 0000 0101
-------------------    异或之后
0000 0000 0000 0110
 
我们发现3 和 4的第二位第三位的值不一样,而且这个位置异或后肯定为1,如果我们以这两位之一为分辨标准,用一个1 进行与操作,就可以将两个数分到不同的组里。再对每组分别求值,就可以得到最终结果。
class Solution {
    public int[] singleNumber(int[] nums) {
    // 第一个不重复的数字
    int a=0;
    //第二个不重复的数字
    int b=0;
    //所有数的异或值
    int xor=0;
    //求出所有数的异或值
    for(int i=0;i<nums.length;i++) xor^=nums[i];
    //定义探针,并且确定两数不同的二进制位
    int div=1;
    while((xor & div)==0) div=div << 1;
    
    //用探针将数分为两组,分别求我们要的两个数 a b
    for(int i=0;i<nums.length;i++){
        if((nums[i] & div)==0) a^=nums[i];
        else b^=nums[i];
    }
    return new int[]{a,b};
     }
}
 
还有一个只出现一次的数字Ⅱ,打算下次位运算学习解决。









