给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
示例 1:
输入: [5,7] 输出: 4
示例 2:
输入: [0,1] 输出: 0
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/bitwise-and-of-numbers-range
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
开始的时候随手写了一个暴力算法:
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int sum = m;
if (n == m) return sum;
for (int i = m + 1; i <= n; i++) {
sum = sum & i;
}
return sum;
}
};
但是这个超时了,超时原因是从0到很大的一个数之间进行运算的时间超了,这时候我想了一下,如果变成0000这种形式那么这个数就不再变了。就更改了下程序。
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int sum = m;
if (n == m) return sum;
for (int i = m + 1; i <= n; i++) {
if (sum == 0) break;
sum = sum & i;
}
return sum;
}
};
但是还是超时,这次超时是因为很大的数进行运算超了,我思考了下大数怎么进行快速的与操作。我可以把大数移位最后再移回来。但是具体怎么操作,我试了试例子。[5,7],就是5:101 6:110 7:111
那么5&6 = 100(4) 4&7 = 100(4)这样看不出来,接着看8:1000 4&8 = 0000 接着看规律,第一个1是第一轮没得,第二个1是第三轮没得,很巧,第一个1在第一位,第二个1在第三位,我进行了很多次实验证明,每一轮都是删一位,所以我们要怎么用这个呢?要移动到什么时候呢,4的那个1其实就是5和7相同的特质所以我们可以把m=5和n=7同时删位数直到m=n时结束,可以推广。
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int count = 0;
while (m != n) {
m >>= 1;
n >>= 1;
count++;
}
m <<= count;
return m;
}
};
这样就通过啦。错了三次,嘤嘤嘤。半个小时一道题,害。
今天又是开心的一天。
总结:连续的数字相与是m和n不断右移直到n=m。