leetcode第201题 数字范围按位与

题目中 0 <= m <= n <= 2147483647,直接使用暴力破解显然耗时很长。所以本题需要思考十进制位和二进制位之间的关系。本题存在三个规律,一旦发现就很容易解决,并且根本无需任何循环操作。
为了方便讲述,用bin(n)表示n的二进制,res表示结果

第一:不管多少位相与,只要有一个0结果必为0,那么9(1001)与5(101)在题中相与的结果是多少呢?
答案是0,因为9相比5多了一位,那么必定[5,9]之间有个8(1000),所以8与5相与结果为0,根本不需要和其他数进行相与操作。
规律一: if bin(n)>bin(m),结果必定为0!
当且仅当bin(n)==bin(m)的时候,res不为0且bin(res)的长度等于bin(n)。

第二:现在只需要考虑n,m的二进制位数相同的情况了,是否直接使用循环呢?
虽然规律一排除了绝大多数可能导致超时的例题,但直接使用循环还是太慢了。如果不用循环,显然我们应该从n,m上找规律。自然我们想到了两数相减,令sub=n-m。
例如n=23(10111),m=19(10011),sub=4(100),也就是m要加4次1.让我们来看看整个过程
第一次:19+1=10011+1=10100=20
第二次:19+2=10011+10=10101=21
第三次:19+3=10011+11=10110=22
第三次:19+4=10011+100=10111=23
我们发现19+4的过程中必定会产生两次进位(20与22的时候),所以[19,23]的过程中,最后一位与倒数第二位必定有0位出现。由规律一知结果二进制位数必定为5位,现在我们可以确定最后两位必定是0。我们不知道倒数第三位会不会产生进位,但不管是否会产生进位,倒数第三位+1之后只有两种情况:原本是0,变成1,原本是1,变成0产生进位,无论哪种,必定相与为0。所以,bin(res)的后bin(sub)位必定为0。
规律二: bin(res)的后bin(sub)位必定为0

第三:我们已经知道了结果res的位数,并且可以根据相减数得到某几位的准确数字。那么res的前几位呢?
至于bin(res)的前几个高位,仍然以19,23为例子,其相减为4,4为三位,那么在19-23的变化过程中,前二位至多只发生一次变化,产生一个进位,例如19(10011)加4,5,6,7,加4不变,加5,6,7只变一次。我们不必在乎[19,23]的过程中是哪一次发生了进位,结果的前两位必定等于19,23两个数字前两位相与。
规律三: bin(res)的除开bin(sub)的前几位就是n与m两个数字前几位相与的结果,与(n,m)区间里的数字无关。

解题思路:
1:如果bin(n)>bin(m),return 0
2:计算bin(n-m)的位数len_sub
3:计算n&m的结果,
4:将n&m前len(n)-len_sub位和len_sub个0相加,就是结果

下面贴上python的代码。

class Solution:
    def rangeBitwiseAnd(self, m: int, n: int) -> int:
        if len(bin(n))>len(bin(m)):
            return 0
        if m==n:
            return m
        sub=len(bin(n-m)[2:])
        return int(bin(m&n)[2:-sub]+'0'*sub,2)

作者:cxm-ee
链接:https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/solution/wu-xu-xun-huan-li-yong-shu-xue-si-wei-qiao-miao-po/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值