Leetcode 201 Bitwise AND of Numbers Range

来源:互联网 发布:超级马里奥mac版 编辑:程序博客网 时间:2024/05/20 17:40

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的个数比较稀疏的话,那么我这个方法就会很有优势,如果不是的话,那么基本上效率是差不多的。

0 0
原创粉丝点击