在LeetCode上做题时,有一道与按位与有关的题,如下:
看到通过率有些纳闷
看题目也不是很难,感觉用一层循环就可以了
第一次尝试的代码:
public static int rangeBitwiseAnd1(int m, int n) {
int result = m;
for (int i = m+1; i <= n; i++) {
result = result&i;
if (result==0) {
break;
}
}
return result;
}
提交失败:Time Limit Exceeded
测试用例是:m=60000,n=2147483647
时间复杂度分析:一层循环O(n),按位与操作32位,常数级O(1);虽然时间复杂度是O(n),但是显然题目要求更加有效率的解法。参考讨论区的帖子,看到很好的例子。
分析思路:如下例子
5 — 0000 0101
6 — 0000 0110
7 — 0000 0111
4 — 0000 0100
1.在数字加1的时候,最低位会从0变成1或从1变成0,按位与结果必然是0;
2.对于8 — 0000 1000 最高位发生改变,那么其之下的位都变成0,那么在按位与过程中,除了最高位其之下的位都将变成0;
3.因此,只要是改变的位,按位与的结果必然是0;
4.数字m经历累加1到达n的过程,必然是从最低位开始改变,直到某个位置及这之上的位都不必再改变;
5.例如从5到7,第一位和第二位都做了改变,并不是只有第二位做了改变,因此一位二位都得0,而相同的没有改变的三位为原来的位数,1;
6.因此,只要找到m和n由最高位(相同)开始的连续的相同位数的片段保留,其余变为零即可。
算法:
1.i=0,右移零位开始判断,两个数相等,返回这个数;
2.i++,将不相等的低位右移,得到m和n由最高位(相同)开始的连续的相同位数的片段;
3.将m被右移的位数左移恢复为零,输出。
事件复杂度O(1)