leetcode 201数字范围按位与

题目:

给定范围 [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)

你可能感兴趣的:(算法随笔)