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)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章