异或小知识

作者: 尉昌达 | 来源:发表于2020-06-14 13:38 被阅读0次
    • >> 带符号位右移 高位根据符号位补齐
    • >>> 不带符号位右移 高位都用0补齐
    • mid = (L + R) / 2 写成 mid = L + ((R-L) >> 1) 防止溢出
    • n * 2 可以写成 n << 1
    • (n * 2)+1 可以写成 ((n << 1) | 1)

    异或运算

    异或运算:相同为0,不同为1
    同或运算:相同以1,不同为0
    所以,异或运算就记成无进位相加!

    • 异或运算的性质
      0^N == N
      N^N == 0
      异或运算满足交换律和结合率(同一批数,异或起来的结果是一样的)
      上面的两个性质用无进位相加来理解就非常的容易

    • 如何不用额外变量交换两个数 (a,b在不同内存)

    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    
    1. 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数
    准备一个 int eor = 0;
    与数组中的所有数异或,最后eor的值就是这种数。
    因为偶数的本身异或都为0了,奇数异或是本身。
    // arr中,只有一种数,出现奇数次
        public static void printOddTimesNum1(int[] arr) {
            int eor = 0;
            for (int i = 0; i < arr.length; i++) {
                eor ^= arr[i];
            }
            System.out.println(eor);
        }
    
    
    1. 怎么把一个int类型的数n,提取出最右侧的1来
    用 n & ((~n) + 1);
     n   = 0 ... 0 1 1 0 1 0 1 0 0 0 0
    ~n   = 1 ... 1 0 0 1 0 1 0 1 1 1 1
    ~n+1 = 1 ... 1 0 0 1 0 1 1 0 0 0 0
    
    ans  = 0 ... 0 0 0 0 0 0 1 0 0 0 0 
    
    1. 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数
    假设2种数是a,b.
    eor 先与数组所有数异或,那么eor = a ^ b != 0,那么 a,b中一定有一位是不一样的,假设他们第8位不一样。
    整个数组可以分为
    1.第8位=1的
    2.第8位=0的
    那么a,b是在这2个不同的组。
    再找有个变量 eor‘ 去同第一组异或,那第一组中偶数的都为0了,剩下的结果就是eor’ = a(设a分在第一组)。
    那么 eor ^ eor' = b.
    
    // arr中,有两种数,出现奇数次
        public static void printOddTimesNum2(int[] arr) {
            int eor = 0;
            for (int i = 0; i < arr.length; i++) {
                eor ^= arr[i];
            }
            // eor = a ^ b
            // eor != 0
            // eor必然有一个位置上是1
            // 0110010000
            // 0000010000
            int rightOne = eor & (~eor + 1); // 提取出最右的1
            int onlyOne = 0; // eor'
            for (int i = 0 ; i < arr.length;i++) {
                //  arr[1] =  111100011110000
                // rightOne=  000000000010000
                if ((arr[i] & rightOne) != 0) {
                    onlyOne ^= arr[i];
                }
            }
            System.out.println(onlyOne + " " + (eor ^ onlyOne));
        }
    
    
    1. 计算二进制中有几个1
    public static int bit1counts(int N) {
            int count = 0;
            
            //   011011010000
            //   000000010000     1
            
            //   011011000000
            // 
            
            
            
            while(N != 0) {
                int rightOne = N & ((~N) + 1);
                count++;
                N ^= rightOne;
                // N -= rightOne
            }
            
            
            return count;
            
        }
    
    

    相关文章

      网友评论

        本文标题:异或小知识

        本文链接:https://www.haomeiwen.com/subject/bcrxxktx.html