算法学习-异或运算(不进位相加)

215 阅读1分钟

异或运算规则

相同为 0 ,不同为 1.

异或运算规律

  1. a ^ 0 = a
  2. a ^ a = 0
  3. a ^ b = b ^ a
  4. a ^ (b ^ c) = (a ^ b) ^ c

应用实例

交换值

function swap(a, b) {
    a = a ^ b
    b = a ^ b // 此时表达式为:a ^ b ^ b => a
    a = a ^ b // 此时表达式为:a ^ b ^ a => b
}

算法题

  1. 有一批数,其中有一个出现了奇数次,其他都出现了偶数次。

问:求这个出现了奇数次的数。

function findNum(arr) {
    let eor = 0;
    for (let i = 0; i < arr.length; i++) {
        eor ^= arr[i];
    }
    return eor;
}
  1. 有一批数,其中有两个出现了奇数次,其他都出现了偶数次。

问:求这两个出现了奇数次的数。

function findNum2(arr) {
    let eor = 0;
    let eor1 = 0;
    for (let i = 0; i < arr.length; i++) {
        eor ^= arr[i];
    }

    const rightOne = eor & (~eor + 1); // 获取最右边的 1

    for (let i = 0; i < arr.length; i++) {
        if ((arr[i] & rightOne) === 0) {
            eor1 ^= arr[i];
        }
    }

    return [eor1, eor ^ eor1];
}

假定两个数分别为 a, b, eor 与数组中每一个元素异或,最后 eor = a ^ b;由题意可知,a != b, 所以 eor != 0;拿到 eor 最右边位为 1 的数 eor1,除 a, b 两个数外,其他出现偶数次的数也会被 eor1 分类,分类规则为这一位上是否为 1,再由 eor1 去异或其中一类,剩下的就是 a 或者 b。