您的位置:首页 > 其它

Leetcode 201 Bitwise AND of Numbers Range

2015-05-25 15:58 302 查看
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.

这道题能找到规律之后会变得非常简单。其实规律很简单,只需要找到n和m的二进制表示里第一个不相同的位,然后把之后的数据全部都抹成0即可(包括第一个不相同的位),至于为什么的话,因为从m到n,如果把每个数都与起来,其实也就是会把所有0出现过的位给清掉了,只要出现一次就会清掉。假设二进制表示里第一个不相同的位是t,那么从m到n的过程中,从第0到第t位(从右边数起),每一位都会出现一次0(证明我不在行,我是没找到反例)。

比如说5到7,

总共是3个数:

【5,6,7】

二进制表示分别为:

【101,110,111】

第0位到第1位都有0出现过,所以最终结果会把这两位都清为0,即100,也就是4。

在求n和m第一个不相同的位的时候,我用到了异或运算,还有利用n&(n-1)清最右边的一个1的技巧,具体看代码吧(果然代码就是最好的注释)。

class Solution {
public:
int getMediaOpVal(int val)
{
int nOpVal = 0;
while(val)
{
nOpVal = val;
val = val & (val - 1);
}
nOpVal = (nOpVal << 1) - 1;
return nOpVal;
}
int rangeBitwiseAnd(int m, int n) {
if(n == m)
return n;
int nMedia = m ^ n;
int nOpVal = getMediaOpVal(nMedia);
return n & (~nOpVal);
}
};


查了一下别人的解法,用到的思路是一样的,都是要找到第一个不相同的位,然后清掉后面的值,只不过技巧不同,看起来比我这个更秀气一些,具体代码如下:

class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int nBitOffset = 0;
while(m && n)
{
if(m == n)
{
return n << nBitOffset;
}
m >>= 1;
n >>= 1;
nBitOffset++;
}
return 0;
}
};


最后发现这个代码比我自己做的要慢,想了想,确实会如此,我自己的方法关心的是第一个不相同的位之后的1的个数,1的个数比较少的话,那么val&(val-1)会大大加快运算速度,而找到的这个做法不是关心1的个数,而是只关心第一个不相同的位是在什么地方,所以当n和m异或出来的结果1的个数比较稀疏的话,那么我这个方法就会很有优势,如果不是的话,那么基本上效率是差不多的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  位运算