异或运算小结| 「掘金日新计划 · 10 月更文挑战」

105 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天

异或运算

  • 性质:0^N==N N^N=0
  • 如果a、b两个值不相同,则异或结果为1。
  • 如果a、b两个值相同,异或结果为0。
  • 异或也叫半加运算,其运算法则相当于不带进位的二进制加法:
  • 二进制下用1表示真,0表示假,则异或的运算法则为: 0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以 异或常被认作不进位加法。

可解决问题类型:

  • 不使用额外变量交换两个数
  • 一组数据中,一种数出现奇数次,其他均出现偶数次(全部异或)
  • 提出数最右侧的一 N&((~N)+1)
  • 获取最低的非0位 N&(~N)
  • 一组数据中,两种数出现奇数次,其他均出现偶数次(全部异或后得到x=a^b,x!=0,x必有一位上是1。提取出x最低位1得x1,ab同位可能为0,1/1,0。令x1和数据元素相与,同为1的全部元素再次异或就可得a/b,再令x异或a/b得b/a)

例题:汉明距离

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

给你两个整数 x 和 y,计算并返回它们之间的汉明距离。

我们使用异或运算,记为 ⊕,当且仅当输入位不同时输出为 1。 计算 x 和 y 之间的汉明距离,可以先计算 x⊕y,然后统计结果中等于 1 的位数。

    public int hammingDistance(int x, int y) {
        int count=0;
        int z=x^y;
        while(z!=0){
            count+=z & 1;
            z=z>>1;
        }
        return count;
    }
}

这里采用的是一种计数法,比较简单粗暴,规则如下:

通过 toString(2)toString(2) ,我们可以将数字转换为对应的二进制数的字符串。 x, y 长度可能不一致,我们需要在较短的数前面补 0 。 对比两个数字字符串,统计多少位不一致即可。

var hammingDistance = function(x, y) {
    x = x.toString(2);
    y = y.toString(2);
    let maxLength = Math.max(x.length, y.length);
    x = x.padStart(maxLength, 0);
    y = y.padStart(maxLength, 0);
    let ans = 0;
    for (let i = 0; i < maxLength; i++) {
        if (x[i] !== y[i]) ans++;
    }
    return ans;
};