算法:异或运算^

Posted nightofstreet

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法:异或运算^相关的知识,希望对你有一定的参考价值。

package club.interview.algorithm.eor;

import java.util.Arrays;

/**
 * 异或运算 == 无进位相加
 * 1. 找到整数二进制最后一个1的下标位置 {@link EorT#findIndexOne(int)}  }
 * 2. 统计整数二进制中1的个数 {@link EorT#countOne(int)}
 * 3. 找到数组中出现奇数次的1个数 {@link EorT#findNumOdd(int[])}
 * 4. 找到数组中出现奇数次的2个数 {@link EorT#findNumOdd2(int[])}
 * <p>
 * 知识点扫盲
 * 1. 异或运算特点
 * *  1.1 N = N ^ 0
 * *  1.2 0 = N ^ N
 * *  1.3 满足交换律和结合律
 * 2. 打印整数的二进制 {@link Integer#toBinaryString(int)}
 * 3. 对数求解 {@link Math#log(double)}
 *
 * @author QuCheng on 2020/6/13.
 */
public class EorT {

    /**
     * 1.找到整数二进制最后一个1的下标位置
     */
    private int findIndexOne(int num) {
        if (num == 0) return -1;
        return log2(num & (~num + 1));
    }

    /**
     * 2. 统计整数二进制中1的个数
     */
    private int countOne(int num) {
        int count = 0;
        while (num != 0) {
            count++;
            int rightOne = num & (~num + 1);
            num ^= rightOne;
        }
        return count;
    }

    /**
     * 3. 找到数组中出现奇数次的1个数
     * ** 数组中有且只有一个数出现过奇数次,找到该数字
     */
    private int findNumOdd(int[] num) {
        int eor = 0;
        for (int i : num) eor ^= i;
        return eor;
    }

    /**
     * 4. 找到数组中出现奇数次的2个数
     * ** 数组中有且只有2个数出现过奇数次,找到该数字
     */
    private int[] findNumOdd2(int[] num) {
        int eor = 0;
        // eor为a^b
        for (int i : num) eor ^= i;

        // eor1 为 a
        int rightAeorB = eor & (~eor + 1);
        int eor1 = 0;
        // 根据rightAeorB二进制中的1将A和B区分开
        for (int i : num)
            if ((i & rightAeorB) == rightAeorB)
                eor1 ^= i;

        // eor 为 b
        eor ^= eor1;
        return new int[]{eor, eor1};
    }


    public static void main(String[] args) {
        EorT e = new EorT();
        System.out.println("二进制打印 : " + Integer.toBinaryString(-2));
        int[] findIndexOne = {-1, 0, 5, 8};
        for (int i : findIndexOne) System.out.println("二进制中最后一个1的位置 " + i + " : " + e.findIndexOne(i));
        System.out.println("------------------");

        for (int i : findIndexOne) System.out.println("二进制中1出现次数 " + i + " : " + e.countOne(i));
        System.out.println("------------------");

        int[] findNumOdd = {12, 12, 5, 3, 6, 12, 3, 5, 6};
        System.out.println("出现奇数次的1个数 " + Arrays.toString(findNumOdd) + " : " + e.findNumOdd(findNumOdd));

        System.out.println("------------------");
        int[] ints = {12, 12, 5, 3, 6, 12, 3, 5, 6, 3};
        System.out.println("出现奇数次的2个数 " + Arrays.toString(ints) + " : " + Arrays.toString(e.findNumOdd2(ints)));
    }


    /**
     * 工具方法:对数求解
     */
    private int log2(int num) {
        return (int) (Math.log(num) / Math.log(2.0));
    }
}

  

以上是关于算法:异或运算^的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段

算法:异或运算^

C++算法——异或运算解决出现次数问题

算法二进制 与或异或运算

基础算法:与或异或运算

《算法零基础100讲》(第46讲) 位运算 (异或) 入门