题目描述:
两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。
给出两个整数 x 和 y,计算它们之间的汉明距离。(统计两个数的二进制表示有多少位不同即可)
注意:
0 ≤ x, y < 231.
示例:
输入: x = 1, y = 4
输出: 2
解释:
1 (0 0 0 1)
4 (0 1 0 0)
↑ ↑
上面的箭头指出了对应二进制位不同的位置。
预备知识:
二进制的异或运算:符号是。当a,b两个数做异或运算时,如果两个值不同,则异或结果为1;如果a、b两个值相同,则异或结果是0。比如 00101
10010=10111。
二进制的与运算:符号是&。运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; 即:两位同时为“1”,结果才为“1”,否则为0。
例如:3&5 即 0000 0011 & 0000 0101 = 0000 0001 因此,3&5的值得1。
例如:9&5 即 0000 1001 (9的二进制补码)&00000101 (5的二进制补码) =00000001 (1的二进制补码)可见9&5=1
二进制移位运算:
- 算数右移:符号是>>。按二进制形式把所有的数字向右移动对应位移位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。例如,11>>2,11的二进制形式为1011,然后把低位的最后两个数字移出,因为该数字是正数,所以在高位补零。则得到的最终结果是0010。转换为十进制是2。在数字没有溢出的前提下,右移一位相当于除2,右移n位相当于除以2的n次方。
- 算数左移:符号是<<。按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。例如,3 << 2。首先把3转换为二进制数字 0011,然后把该数字高位(左侧)的两个零移出,其他的数字都朝左平移2位,最后在低位(右侧)的两个空位补零。则得到的最终结果是1100,则转换为十进制是12。在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方
- 无符号右移:按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补零。对于正数来说和带符号右移相同,对于负数来说不同。
其他结构和>>相似
位运算技巧:
n&(n-1) 去除 n 的位级表示中最低的那一位 1。例如对于二进制表示 01011011,减去 1 得到 01011010,这两个数相与得到 01011010。
01011011 &
01011010
--------
01011010
题解:
思路:本题要计算两个二进制位数不同的个数,所以可以采用异或运算的方法,然后统计出结果有多少个1,则表示两个数有多少个二进制位是不同的。
为了计算等于 1
的位数,可以将每个位移动到最左侧或最右侧,然后检查该位是否为 1
。更准确的说,应该进行逻辑移位,移入零替换丢弃的位。
这里采用右移位,每个位置都会被移动到最右边。移位后检查最右位的位是否为 1 即可。检查最右位是否为 1,可以使用取模运算(i % 2)或者 AND 操作(i & 1),这两个操作都会屏蔽最右位以外的其他位。
要计算判断最后一位是不是1,还可以使用位运算技巧的 z&(z-1) 去除 z 位级表示最低的那一位。
代码1:用z&1判断最后一位是不是1。并统计个数。
class Solution {
public:
int hammingDistance(int x, int y) {
int z=x^y;
int ch=0;
while(z!=0)
{
if(z&1==1)ch++;
z=z>>1;
}
return ch;
}
};
代码2:用z&(z-1)每次去除最低位的1。并统计个数
class Solution {
public:
int hammingDistance(int x, int y) {
int z=x^y;
int ch=0;
while(z!=0)
{
z&=z-1;
ch++;
}
return ch;
}
};
代码: