LeetCode29-兩數相除
2018/11/29
我們學校125週年校慶
普校同慶
學校給發了免費的魚丸湯
雖說魚丸真的不咋地,哈哈哈哈
但真的挺開心的
感受到了學校濃厚的人文氣息
不多說了,直接上圖
29-兩數相除
給定兩個整數,被除數 dividend
和除數 divisor
。將兩數相除,要求不使用乘法、除法和 mod 運算子。
返回被除數 dividend
除以除數 divisor
得到的商。
示例 1:
輸入: dividend = 10, divisor = 3
輸出: 3
示例 2:
輸入: dividend = 7, divisor = -3
輸出: -2
說明:
- 被除數和除數均為 32 位有符號整數。
- 除數不為 0。
- 假設我們的環境只能儲存 32 位有符號整數,其數值範圍是 [−231, 231 − 1]。本題中,如果除法結果溢位,則返回 231 − 1。
這一題剛開始看的時候一臉懵逼,乘法和mod取餘都不能用,那還做個屁啊(弱雞吐槽,大佬們看著樂樂就行哈)最後突然靈光一閃,想到了用加法來做,就是每次將被除數以固定的倍數增加(此處就是它自身),以此來逼近除數,它增加的次數就是商。Perfect 瞬間覺得自己是個天才,不費九牛二虎之力很快就把程式編出來了,興沖沖的放到答題板上run 我還在期待著它的執行效率有多快,誰知道顯示的是大寫的Red:超出時間限制。大家先看程式碼吧!
程式碼如下:
class Solution: # 將被除數以步長為自身的增加去逼近除數 def divide(self, dividend, divisor): """ :type dividend: int :type divisor: int :rtype: int """ if divisor == 0: return 2 ** 31 - 1 shang = 0 flag = 1 if divisor * dividend > 0 else -1 divisor = abs(divisor) dividend = abs(dividend) divisor_copy = divisor # 每次迭代,步長shang都是1倍增長 while divisor <= dividend: shang += 1 divisor += divisor_copy if -2**31 <= flag*shang <= 2**31 - 1: return flag*shang else: return 2**31 - 1 if __name__ == "__main__": dividend = -7 divisor = 2 result = Solution().divide(dividend, divisor) print(result)
不知道大家看完之後有沒有知道是哪兒出問題了導致執行時間過長,如果很快就知道了,那說明你的演算法涵養是真的不錯了。其實問題就是當除數過大,被除數過小時,此時消耗時間過長。比如22229999999除以2,如果按照我上面的程式來每次增加2,這得算到什麼時候啊!就算是計算機也hold不住(當然我這兒的計算機指代的是我們窮學生用的普通配置的筆記本),所以我們接下來要優化的就是被除數每次迭代的步長值,就拿上面那個例子來說:如果每次迭代的步長值也能呈倍數增加,那可以減少很多不必要的計算了,時間自然也是大大的縮短了。那說到這兒很多筆友就會問了:你說的倒是頭頭是道,那怎麼實現呢?各位別急,我剛開始也是想不通,後來在網上看到了一位大佬寫的,覺得茅塞頓開。核心思想就是:使用神器位操作Bit Operation
過程:將一個數左移一位也就相當於將這個是乘以2,我們將除數左移一位也就是相當於將他乘以2,任何一個整數都可以用二進位制的形式來表示,用二進位制表示的最小單位是1,而這裡使用的是最小的單位是這個除數,這樣就可以移動的方式來觀察被除數中到底有多少個除數,最後將這些數做和,返回就OK了。
程式碼如下:
class Solution:
def divide(self, dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
#首先這一句就很python,postive 為true是符號相同
positive = (dividend < 0) is (divisor < 0)
dividend, divisor = abs(dividend), abs(divisor)
res = 0
#檢查dividend是否大於divisor
#如果還小於則進行小精度的逼近dividend
while dividend >= divisor:
temp, i = divisor, 1
#增大逼近dividend的步伐
#i不斷增加, temp不斷減少
while dividend >= temp:
#經過上一句的判斷,所以dividend還大於0
dividend -= temp
#商要加對應的i
res += i
#倍數相應的要增加
i = i<<1
print("i", i)
#目前的值也要不斷的增加
temp = temp<<1
print("temp", temp)
#判定正負號
if not positive:
res = -res
return min(max(-2147483648,res), 2147483647)
if __name__ == "__main__":
dividend = -2147483648
divisor = 1
result = Solution().divide(dividend, divisor)
print(result)
最後的執行效率也算是中上等吧,在70%左右。