题目原文:
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]内所有整数按位与起来的值。
题目分析:
方法一:(分治法)若存在k∈[0,31],使得
m≤2k<n<2k+1,
则返回0,因为[m,n]的二进制数的第k位必定是有0也有1,且第k+1位都是0.而如果
2k≤m<n<2k+1
,则[m,n]的第k位全是1,那么结果就是
2k+[m−2k,n−2k]
区间相与值,这样不断降低问题规模,最终会只剩1-2个数,(因为终究会跟2比一次),直接返回m&n即可。
方法二:(基于位运算,来自http://blog.csdn.net/xudli/article/details/45912649博客)归根结底本题要求的是m和n二进制数的公共前缀,所以先按位右移,记录下移动位数,再按位左移回去即为所求。
源码:(language:java)
方法一:
public class Solution {
private static int[] pows = new int[]{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824};
public static int rangeBitwiseAnd(int m, int n) {
if(m>pows[30])
return pows[30] + rangeBitwiseAnd(m-pows[30],n-pows[30]);
for(int i = 1;i < 31; i++) {
if(m<pows[i] && n>pows[i])
return 0;
else if(m>=pows[i] && n<pows[i+1])
return pows[i] + rangeBitwiseAnd(m-pows[i],n-pows[i]);
}
return m&n;
}
}
方法二:
public class Solution {
public int rangeBitwiseAnd(int m, int n) {
int bit = 0;
while(m!=n) {
m>>=1;
n>>=1;
bit++;
}
return m<<bit;
}
}
成绩:
都是9ms,beats 19.89%,众数9ms,42.27%
Cmershen的碎碎念:
第二种想法十分巧妙也容易理解,但第一种想法更为朴素。