算法学习(2):位运算|、^、&的介绍和使用

|、^、&、~的介绍

| 是按位或运算符号,&是按位与运算符,^是按位异或运算符,~是按位取反运算符.

| 指的是参加运算的两个对象,按二进制位进行"或"运算.

0|0=0 0|1=1 1|1=1 1|0=1

结论是 按二进制位进行"或"运算,都为0时的运算结果等于0,其他情况都为1.

& 指的是参加运算的两个对象,按二进制位进行"与"运算.

0&0=0 0&1=0 1&1=1 1&0=0

结论是 按二进制位进行"与"运算,都为1时的运算结果等于1,其他情况都为0.

^ 指的是参加运算的两个对象,按二进制位进行"异或"运算.

0^0=0 0^1=1 1^0=1 1^1=0

结论是 按二进制位进行"异或"运算,两个二进制数相同时的运算结果等于0,不同时结果为1.
所以设一个数为a(代表任何数),a^0=a, a^a=0,并且 a ^ b ^ b=b ^ a ^ b =a,即 ^ 异或运算的顺序不会影响结果.

~ 指的是参加运算的两个对象,按二进制位进行"取反"运算.

~0=1 ~1=0

结论是 按二进制位进行"取反"运算,0变成1,1变成0.注意这里说的是在二进制位上0变成1,1变成0,对十进制的0和1进行~取反运算,(int类型)0的二进制是32个0,取反就是32个1,有符号的情况下就等于-1(其他类型结果不变).1同理(int类型)前面都是0最后一个是1,取反前面31个1最后一个0,有符号的情况下就等于-2.

|、^、&、~的使用

题目1:

给定一个非空整数数组,除了某个元素只出现奇数次以外,其余每个元素均出现偶数次。找出那个出现了奇数次的元素。

代码:

        int o=0;
        for (int i : arr) {
            o=o^i;
        }
        return o;

解析:

这里有两个条件,一个出现奇数次的元素,和其他元素均出现偶数次.所以排除所有出现偶数次的元素就能获取剩下的出现奇数次的元素,上面介绍^ 异或运算时提到相同的数异或自己时结果是0,0异或任何数结果不会变化,而且 ^ 异或运算的顺序不会影响结果.所以将数组里所有数遍历都进行异或运算,偶数次元素异或后变成0,奇数次的元素最后剩下自己.

题目2:

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

代码:

	    public int hammingWeight(int n) {
        int m = 0;
        while (n != 0) {
            n = (n - 1) & n;
            m++;
        }
        return m;
    }

解析:

n-1之后去和n进行与运算,n-1之后二进制位最右侧的1会变成0,比如1111变成1110,1110变成1101,和原数字与运算后本来最右侧的1之后的二进制位的1不会变动,然后循环重复操作直到变成二进制位都变成0;

代码:

    public int hammingWeight(int n) {
        int num = 0;
        while (n != 0) {
            if ((n & (~n + 1)) != 0) {
                n = n - (n & (~n + 1));
                num++;
            }
        }
        return num;
    }

解析:

第二段代码n & (~n + 1)其实是查询二进制位最右侧的1,比如1110取反+1 等于0010 与运算(int类型32位二进制位原数字前面都是0,取反后变成1,与运算后还是0)后获取二进制10.后面n - (n & (~n + 1))就是去掉找到的那个二进制位最右侧的1,然后循环.

你可能感兴趣的:(算法,java)