我自己最初的解法,愚蠢至极:
class Solution {
public:
int hammingDistance(int x, int y)
{
int x1[32];
int x2[32];
int i = 31;
int sum=0;
for (i; i >=0; i--)
{
x1[i] = x % 2;
x = x / 2;
x2[i] = y % 2;
y = y / 2;
}
for (i = 0; i <= 31; i++)
if (x1[i] != x2[i]) sum = sum + 1;
return sum;
}
};
C++中把int型作为二进制数,可以直接使用 ^异或、&与、>>右移、<<左移等位运算符对int进行操作:问题转化为怎样最快计算一个二进制数中1的个数。
异或:2^4=6 (010^100=110)
左移:将一个位信息串向左移指定的位,右端用0补充,左端移出的位被丢弃。在信息没有丢失的情况下每左移一位相当于*2。
右移:将一个位信息串向右移指定的位,右端移出的位被丢弃。左端:无符号数用0补充,有符号正数(符号位为0)用0补充,有符号负数(符号位为1)取决于计算机系统(用0补充的系统为逻辑右移,用1补充的系统为算术右移)。但问题是计算机里的数都是按补码(有符号数取反取补符号位都不变)存的,所以在C++运行 -2>>1会输出-1。
需要考虑的问题:
数字的符号。
方法一:两个数做异或之后得到tmp。先判断符号,把数字统一成正数。每次最后一位和1做与运算,计数。
int CountOne(int tmp)
{
int count=0;
if(0==tmp)
return count;
else if(tmp>0)
{
while(tmp)
{
if(tmp&1)
++count;
tmp=tmp>>1;
}
}
else
{
tmp=-tmp;
count=1;
while(tmp)
{
if(tmp&1)
++count;
tmp=tmp>>1;
}
}
return count;
}
方法二:不对异或结果tmp进行右移,反之对用来做与运算的“1”进行左移。可以不用判断符号。
int CountOneVersion2(int tmp)
{
int flag=1;
int count=0;
while(flag)
{
if(flag&tmp)
++count;
flag=flag<<1;
}
return count;
}
方法三:
为奇数(n的二进制表示的末位为1):
n: xxxxxxxx1
n-1: xxxxxxxx0
n&(n-1): xxxxxxxx0
相当于去掉最右边的一个1。
n为偶数且不等于0(n的二进制表示的末位为0):
n: xxxxx1000
n-1: xxxxx0111
n&(n1-): xxxxx0000
也是相当于去掉最右边的一个1。
一直循环直到为0,即为所有1的个数。
int CountOneVersion3(int n)
{
int count=0;
while(n)
{
++count;
n=n&(n-1);
}
return count;
}
方法四:计算快速汉明距离
看不懂原理,先存着。