記一次失敗的解題經歷,想跑捷徑,最後發現還是最初的起點比較快
題目如下
201. 數字範圍按位與
難度中等112收藏分享切換為英文關注反饋
給定範圍 [m, n],其中 0 <= m <= n <= 2147483647,返回此範圍內所有數字的按位與(包含 m, n 兩端點)。
示例 1:
輸入: [5,7]
輸出: 4
示例 2:
輸入: [0,1]
輸出: 0
解題優化程度遠不如官方,想學習優化演算法可以看官方題解
此處記錄思路過程,以及總結經驗
解題**如下
class solution:
def change(self,m:int) -> int:
temp = bin(m)[2:]
temp= [i for i in str(temp)]
change = false
for i in range(len(temp)-1,-1,-1):
if temp[i] == '1':
temp[i] = '0'
change = true
elif change:
temp[i] = '1'
break
temp = ''.join(temp)
if int(temp) == 0:
temp = '1' + temp
return int(temp, 2)
def rangebitwiseand(self, m: int, n: int) -> int:
if m == 0:
return 0
temp = m
result = m
while temp <= n:
result = result & temp
if result == 0:
return 0
temp = self.change(temp)
return result
思路過程如下
# 思路1(失敗),首先把所有數字按照題目要求,暴力法進行按位與,看起來似乎是個可行操作,但是經過測試在使用range()時,記憶體超標
【第乙個想法明顯是會超標的,只是初始化試試,並且寫乙個demo,用於以後測試其他演算法結果是否一致】
【第二個想法只是測試一下單純快速短路演算法能否解決,結果也不行】
# 思路3(失敗),上述思路失敗後,可以得知,如果正常方法是只會超時的,因此如果想解決,發現其中規律,此時整理一下手中,在不便利所有字元 情況下,能獲取到的條件
能獲取到的是,起始字元m,結束字元n,以及中間會遍歷的位數m-n+1,思路步驟第三步,思路2的函式並沒有錯誤,只是會超時,那麼用思路2的函式進行輸出結果來檢視是否有規律
從結果可以得出是有規律的,在中間相同數字的按位與結果往往有較多重複,隨後我隨機以乙個數字174為起點,遍歷輸出結果,得到(174,174到175)結果為174,(174,176到191)結果為160,(174,192到255)結果為128,(174,256以及後面)結果都為0
然後可以看出,174到175為2個數,176到191為16個數,192到255為64個數,然後計算174的二進位制結果為"10101110",160二進位制為10100000(正好消除的位數到2^4=16),128二進位制為10000000(消除到2^6=64)
從而聯想,是否可以這麼計算,m和n按位與,首先,計算m的二進位制,以上述的174為例,首先計算174的二進位制為10101110,隨後174與174+1進行按位與,隨後結果持續2^(174-174=0)位,隨後把上次的結果174按位與174+1+2^(174-174,結果取最高二進位制為0)得到結果160
隨後結果持續2^(174-160=14,結果取最高二進位制為4),隨後把上次的結果160按位與174+1+2^(174-174,結果取最高二進位制為0)+2^4得到結果128....(超時,中間部分邏輯錯誤,跳躍幅度不夠)
【第三個想法,認真檢視了結果,通過重複數字次數較多得知必然有規律,但是逆推規律依舊比較難,中間漏了許多要素,也難以優化】
# 思路4,從上述結果,得知從結果推算規律雖然有可能,但是依舊十分困難,所以就不通過結果推算規律了,直接從按位與的邏輯推算規律,首先按位與只有同時為1的情況結果會為0,
# 那麼依舊從上面的174進行假設,二進位制為10101110,希望改變多出個0的話,下乙個結果促使改變的結果應該為10110000即176【即把倒數第乙個1變成0,但是因為數字只會上公升不會下降,因此向前進1位】
# 這個結果恰好與思路3裡遍歷出的結果相同,176後乙個促使變化的數為後面步驟相同11000000即192,從而得知結果正確
【第四個想法成功解決了問題,但是這個直接從按位與邏輯推算規律的東西,我在第二個想法的時候有思考過,但是感覺可能逆推比較容易就放棄了,最後發現這個規律推算並不難,反而第三個想法裡逆推規律用來乙個小時推算了乙個錯誤規律,第四個想法反而只花了20分鐘不到,雖然裡面也有第三個想法推算時,已經總結到一些關鍵的緣故,但依然是個錯誤】
在未知演算法原理時,推算規律時,可以嘗試用暴力法做個demo,遍歷一批答案,檢視結果是否有序,獲取有什麼規律【如重複數字,奇數偶數。2的n次方加一,等差數列】。但是在已知演算法原理的情況下,建議從原理推算演算法各個步驟需要進行的變化。
leetcode 201 數字範圍按位與
顯然,暴力解決方法是從m開始直到n求按位與,但很明顯這太慢了,雖然時間複雜度是o n 但顯然不是乙個好的解法 我們可以注意到這樣一點,在數字加1的時候,最低位肯定會從0變成1,或者從1變成0,不管哪樣,兩個數的最低位中勢必有乙個0,而一旦出現了乙個0,這一位上的按位與結果將永遠為0 假如在m n的增...
leetcode201 數字範圍按位與
給定範圍 m,n 其中 0 m n 2147483647,返回此範圍內所有數字的按位與 包含 m,n 兩端點 示例 1 輸入 5 7 輸出 4示例 2 輸入 0 1 輸出 0首先,如果m 0,則範圍內按位與的結果必定是0 如果m n 則表示範圍內只有乙個數字,結果必定是m 假設 m 5,n 7 首先...
leetcode 201 數字範圍按位與
題目描述 給定範圍 m,n 其中 0 m n 2147483647,返回此範圍內所有數字的按位與 包含 m,n 兩端點 示例 1 輸入 5,7 輸出 4 示例 2 輸入 0,1 輸出 0 class solution while m n return n return n shift 外加乙個求漢明...