leetcode:201. 数字范围按位与

题目来源

题目描述

在这里插入图片描述

class Solution {
public:
    int rangeBitwiseAnd(int left, int right) {

    }
};

题目解析

分析数据

  • 区间范围很大,区间一定是正数

思路

在这里插入图片描述

算法

问题的本质是求解m和n的最长公共前缀,如果m==n直接返回。如果m<n,那一定是以下的形式。

m:  S S S 0 X X X X
n:  S S S 1 X X X X

上面的S代表相等,X代表未知(不一定相等)。那数字范围按位与的结果,应该为:

S S S 0 0 0 0 0

S S S 部分

算法

  • 两数都向右移,直到移到他俩相等,这样就找到了他俩的公共前缀
  • 刚刚向右移了几位,现在再向左移几位,这样的话就相当于把非公共前缀后面的非零位都变成0
class Solution {
public:
    int rangeBitwiseAnd(int left, int right) {
        int shift = 0;
        // 为什么是 left != right 因为保证的是不能全移没了,
        // 向右位移 最后的结果是 left 和 right 找到二进制位的公共前缀  这时候left 和right 已经相等了
        while (left != right) {
            // 都同步向右移
            left >>= 1;
            right >>= 1;
            // 记录移动的次数
            ++shift;
        }
        // 再向左移动刚刚向右移动的次数
        return left << shift;
    }
};

清除二进制串中最右边的 1

还有一个位移相关的算法叫做「Brian Kernighan 算法」,它用于清除二进制串中最右边的 11。

Brian Kernighan 算法的关键在于我们每次对number 和 number−1 之间进行按位与运算后,number 中最右边的 1 会被抹去变成 0。

在这里插入图片描述
基于上述技巧,我们可以用它来计算两个二进制字符串的公共前缀。

其思想是,对于给定的范围 [m,n](m<n),我们可以对数字 n迭代地应用上述技巧,清除最右边的 1,直到它小于或等于 m,此时非公共前缀部分的 1 均被消去。因此最后我们返回 n 即可。

class Solution {
public:
    int rangeBitwiseAnd(int left, int right) {
        while (left < right){
            right = right & (right - 1);
        }
        return right;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值