题目:
给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
示例 1:
输入: [5,7] 输出: 4
示例 2:
输入: [0,1] 输出: 0
那个啥。。。不会有人想用循环一点点“&”出来吧?
不过我觉得这题虽然最终结果很简单,但是我却提交了好几次,每次都是细节,思维的不足。
第一步当然先观察嘛。
5=(【28个0】0101)
7=(【28个0】0111)
中间夹杂的是6=(【28个0】0110)
我发现只要这中间有一个数字的第k为是0,那么答案的第k位肯定是0。
所以第一回想着测试最高位的1在哪里,如果不一样,那么直接返回0。
如果一样,那么返回把最高位置1的数字。
比如5最高位1是第3位,7也是,那么我返回1<<(3-1)啊。就是4。
可惜我这个想法实在不对,没有考虑接下来的位。
比如12=(【28个0】1100),15=(【28个0】1111)
实际上应该返回12,所以远远不是设置一个1 就可以解决的。
所以我又猜测是“1”的范围,制作了一个小函数来寻找最高位的1、最低位的1。
用公共部分的1来置位,因为这个方法是错误的,所以不贴代码,但是依然失败了(说白了这个方法只能对某些mn返回正确结果)。
最后我发现是跟m、n的相似度有关系。
所以我用了一个数组来记录有多少公共的部分,并且舍弃低位的不相似部分。
事实证明,最终结果仅仅与高位、并且相同的位有关。
其实实际上也就相当于 n&n=n的道理,只是添加、移动了位模式。
哎,太傻,没想到。
所以最终我用字符串与int解析函数完成了答案,时间复杂度是O(1),空间O(1)。(实际上就是64次搜索外加长度32的保存数组)
代码如下:
class Solution(object):
def rangeBitwiseAnd(self, m, n):
def h(m, n):
a = bin(m)[2:]
b = bin(n)[2:]
a = '0' * (32 - len(a)) + a
b = '0' * (32 - len(b)) + b
arr = ['0' for x in range(32)]
for i in range(32):
if a[i] != b[i]:
break
if a[i] == '1' and b[i] == '1':
arr[i] = '1'
return int(''.join(arr), 2)
return h(m,n)