Leetcode461:汉明距离(对位的小总结)

思路1:
首先根据题目确定数字的位数最多31位。其实就是依次判断对应位是否相同。可以通过对数字进行右移然后判断最低位是否相同。最低位我们知道是决定奇偶的。所以直接通过对x y奇偶是否相同进行判断即可~
代码:

class Solution {
public:
    int hammingDistance(int x, int y) {
    int count=0;
    for(int i=1; i<=31;i++){
        if(x%2!=y%2)
           count+=1;
         x=x>>1; y=y>>1;
    }
    return count; 
    }
};

思路2:
   思路2和思路1差不多,但是能减少一定的时间复杂度。主要利用了异或的性质。不同位输出1,相同位输出0,而我们正是要不同位。问题就变成了检测异或结果中1位的个数:

class Solution {
public:
    int hammingDistance(int x, int y) {
        int s = x ^ y, ret = 0;
        while (s) {
            ret += s & 1; // 注意到出了%2 也可以用 s与1来&位与实现最后1位是否1的判断。因为1前面都是0,输出与肯定都是0,所以输出是否1看s的最后1位是不是1.所以也是判断奇偶的
            s >>= 1;
        }
        return ret;
    }
};

思路3:
   思路三很巧妙,主要用到了Brian Kernighan 算法,这个算法的性质可以拿来活用。
   在方法二中,对于 s=(10001100)2 的情况,我们需要循环右移 8次才能得到答案。而实际上如果我们可以跳过两个 11 之间的 00,直接对 11 进行计数,那么就只需要循环 3次即可。
  我们可以使用 Brian Kernighan 算法进行优化,具体地,该算法可以被描述为这样一个结论:
  记 f(x)表示x 和 x−1 进行与运算所得的结果(即 f(x)=x & (x−1)),那么 f(x) 恰为 x删去其二进制表示中最右侧的 1的结果。
  基于该算法,当我们计算出 s=x⊕y,只需要不断让 s=f(s),直到 s=0 即可。这样每循环一次,s都会删去其二进制表示中最右侧的 1,最终循环的次数即为 s 的二进制表示中 1的数量。

class Solution {
public:
    int hammingDistance(int x, int y) {
        int s = x ^ y, ret = 0;
        while (s) {
            s &= s - 1;
            ret++;
        }
        return ret;
    }
};

总结:
   1. x%2 或者x&1==1?帮助我们判断数字的奇偶或者说他们最后一位是1还是0.并通过左移实现多位判断。
   2. 异或性质帮助我们找出两个二进制中不同位并且标号1
   3. 说白了 Brian Kernighan算法的性质能帮助我们快速统计二进制中等于1的位数!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值