题目:数字范围位相与
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,返回这个范围内所有数字相与之后的结果。
转载:http://www.cnblogs.com/grandyang/p/4431646.html
思路一:
从题目中给的例子来分析,[5, 7]里共有三个数字,分别写出它们的二进制为:
101 110 111
相与后的结果为100,仔细观察我们可以得出,最后的数是该数字范围内所有的数的左边共同的部分,如果上面那个例子不太明显,我们再来看一个范围[26, 30],它们的二进制如下:
11010 11011 11100 11101 11110
发现了规律后,我们只要写代码找到左边公共的部分即可,我们可以从建立一个32位都是1的mask,然后每次向左移一位,比较m和n是否相同,不同再继续左移一位,直至相同,然后把m和mask相与就是最终结果。
代码:C++版:64ms
class Solution { public: int rangeBitwiseAnd(int m, int n) { int d = INT_MAX; while ((m & d) != (n & d)) { d <<= 1; //左移一位,右边补0,清除掉m和n不相同的位,相同的位依然为1 } return m & d; //d中为1的位表示m和n中都同时为1的位 } };
思路二:
另一种解法,不需要用mask,直接平移m和n,每次向右移一位,直到m和n相等,记录下所有平移的次数i,然后再把m左移i位即为最终结果。
代码:C++版:68ms
class Solution { public: int rangeBitwiseAnd(int m, int n) { int i = 0; while (m != n) { m >>= 1; n >>= 1; ++i; } return (m << i); } };
思路三:
递归实现,观察如上规律可得,如果m < n,那么返回数字的最低位一定是0,所以可以将该问题转换为如下子问题:rangeBitwiseAnd(m>>1, n>>1)。
代码:C++版:72ms
class Solution { public: int rangeBitwiseAnd(int m, int n) { return (n > m) ? (rangeBitwiseAnd(m/2, n/2) << 1) : m; } };