Leetcode201-Bitwise AND of Numbers Range

今天看到Leetcode又有新题了。

原题:

Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.For example, given the range [5, 7], you should return 4.

题意:

给定一个范围[m, n],0 <= m <= n <= 2147483647,求出该范围内所有数按位与(&)操作后的结果。比如范围[5, 7],为5&6&7 = 4。

分析:

如果真的在范围[m, n]内按顺序逐个数字做&操作显然效率不高。那么我们可以先列出一些数字去寻找规律:

00
11
210
311
4100
5101
6110
7111
81000
91001
101010
111011
121100
131101
141110
151111
......
由上表不难发现不同位上的变化规律不同。而右移操作>>会抹去末端一位

再看其中的一个区间,举例[12, 15]:

12110011011
13110111011
14111011111
15111111111
上表区间中在移位过程中,逐渐抹去最后一位,最终会在某一次移位后区间内所有数的值相同(1101->110->11),移位次数为2,该范围内所有数按位与操作以后结果为1100,即12。由此我们可以知道,低位部分在范围内按位与操作中会因为0的存在而消去为0,只有高位部分会得以保留。因此我们可以用一个count计数器记录移位次数(即低位0的个数),而最终移位结果均一致时(如例子中最终为二进制11),即为其高位部分。此时只需将高位部分复原即可,也就是11->110->1100,做2次向左移位复原。

当然在计算过程中我们并不需要对区间内所有数做这种操作,只需对区间最小值m和最大值n进行操作(因为区间首尾是区分度最大的两个数,对区间内所有数做右移时,最有可能不相同的肯定是m和n)。

注意:

当较小的数移位后为0时,就应该停止循环。最终结果肯定也是0。

如果还有困惑请看Ac代码。


AC代码(C++实现):

class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        int count = 0;//初始化计数器
        while (m && m != n) {//m为0时或m == n时退出循环
        	++count;//统计低位0的个数
        	m >>= 1; n >>= 1;//抹去低位
        }
        return m << count;//低位复原, 因为0 << count仍为0, 因此此处不做区分
    }
};

如代码或分析有误请批评指正,欢迎讨论。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值