leetcode 461 Hamming Distance(位操作入门)

题目来源:LeetCode 461

简单题目分析:
求a和b二进制表示中,一共有多少不同的位。例如1的二进制表示为0001,4的二进制表示为0100,那么1和4不同的位是2.
一开始我的思路很简单,直接遍历32位整数的每一位,代码如下:

int hammingDistance(int x, int y) 
{
   int i,ans=0;
   for(i=0;i<32;++i)
   {
       if((x&1)!=(y&1))
         ans++;
       x>>=1;y>>=1;
   }
   return ans;
}


凡是涉及到二进制的问题,大多数都会与位操作有些联系。C&C++&Python(只熟悉这三种语言...)都对位操作有相关的支持,简单介绍如下:
~ :取反操作,将二进制的每一位取反,0变成1,1变成0,注意int整型取反操作后,最高位1之前的所有0也会变成1,所以大多数整数取反后会变成负数。
& :与运算,这个和逻辑与的作用大抵相似,对于位数相同的两个二进制数,如果对应位都是1,那么运算后的相应位也是1(两个都是真结果才为真)。
|  :或运算,这个和逻辑或的作用大抵相似,对于位数相同的两个二进制数,如果对应位有一个为1,那么运算后的相应为也是1(有一个为真结果就为真)。
^ :异或运算,相应位不同结果为1,否则是0。
>>和<< :这是两个运算符,分别是右移运算和左移运算,例如a>>1是把a的二进制表示向右移一位,低位舍去高位补0(简单而言,其实还有更复杂的机制)。
有了上述知识,我们就可以来分析一下上述的代码了。
1. 首先对于int整型,一般计算机会存储32位,只不过在最高位1前面补0罢了,所以我直接遍历32位。
2. x&1这个操作有一个特殊的用处,那就是判断x的奇偶性。因为如果一个数是奇数,那么它的二进制最低位就是1,偶数则为0,用这个数对1进行与操作就可以判断奇偶(自己手动实现一下就可以知道这个原理),除了判断奇偶,x&1更广泛意义上是判断x的最低位是1还是0。因此那句if的作用就是如果x和y的最低位不相同,ans就增加。
3. x>>=1,y>>=1的作用就不必多说。

代码就分析为止,还是挺简单的吧,但是我提交完我的代码后,尽管AC但是效率异常低...Orz
于是,我看了其他人的代码。
于是,我发现了新天地...原来还有这种位操作?!

扩展1:
测试第n位比特。(将最低位视为0位)
这个原理和x&1一样,只不过改成x&(1<<n)。
1<<n的意思就是左移n位,以8位比特为例:
1的二进制表示为00000001
1<<1 00000010
1<<2 00000100
1<<3 00001000
自己手动试一下x&(1<<n),就可以发现它的作用。

扩展2:
把第n位比特设为1。
只需要把扩展1改一下即可,变成x | (1<<n)
注意 | 的作用,相应位只要有一个1那么结果就是1,通过这个特性,1<<n的第n位一定是1,那么 x|(1<<n)的第n位一定是1。

扩展3:
把第n位比特设为0。
x & ~(1<<n)
具体原理不再赘述,自己手动试一下就明白了。

扩展4:
把第n位比特取反。
x ^ (1<<n)

上述操作的基础都是在1<<n上,这个二进制还是有很大的用处的。另外要十分熟悉各种位操作的特性,根据这些就扩展出很多东西。这只是位操作的入门篇,过几天我应该会补充上几个更高级的操作(大雾)。

最后再附上两个版本的代码(依旧是这个题):
首先是C的,既然要求不同位,我们就可以想到异或操作,异或完二进制中1的个数就是答案,那么:
int hammingDistance(int x, int y) 
{
   int ans=0,temp=x^y;
   while(temp)
   {
       if(temp&1)
        ans++;
       temp>>=1;
   }
   return ans;
}

最后再来一个Python的,最近在学python...
class Solution(object):
    def hammingDistance(self, x, y):
        """
        :type x: int
        :type y: int
        :rtype: int
        """
        return bin(x^y).count('1')

稍微解释一下,“”“三引号可以引用多行字符串,bin(x)是一个内置函数,返回x的二进制表示字符串,count()函数是计算字串出现的次数,至于类括号里面的(object)和函数的self参数,以后有空再说(不知不觉立了好多flag)...

同学们,再见。

感谢参考博客: 谢谢原博主   http://www.cnblogs.com/programnote/p/4686330.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值