1. 程式人生 > >LeetCode29-兩數相除

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%左右。