翻倍快-LeetCode29-兩數相除
阿新 • • 發佈:2018-12-04
題目
給定兩個整數,被除數 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。
須知
實際上餘數不能為負數。例如-10/3=-4...2而不是-10/3=-3..-1。但是,計算機不這麼認為,計算機認為-10/3=-3..-1。
10/3=3...1
10/(-3)=-3...1
-10/3=-3...-1
-10/(-3)=3...-1
所以,只要計算被除數絕對值/除數絕對值的結果。如果被除數除數都正或都負,則結果即為所求。如果被除數除數一正一負或一負一正,則結果前加負號。
思路1
以200/7為例。7 + 7 + 7 + 7 … + 7累加到200,數加了多少次。超時。
思路2
7:1個7。
翻倍 14:2個7。
翻倍 28:4個7。
翻倍 56:8個7。
翻倍 112:16個7。
翻倍 224:32個7。
然後 200-112=88,以88作為被除數繼續進行。
程式碼2
class Solution { public int divide(int dividend, int divisor) { // 考慮結果溢位 if(dividend==-2147483648 && divisor==-1){ return 2147483647; } if(dividend==-2147483648 && divisor==1){ return -2147483648; } // a/b long a=(long)dividend; long b=(long)divisor; if(dividend<0){ a=-(long)dividend; } if(divisor<0){ b=-(long)divisor; } if(a<b){ return 0; } int res=0; while(true){ if(a<b){ break; } // sum:count*b; sum型別為long防止int溢位 long sum=b; // count計數,幾個b int count=1; while(true){ if((sum+sum) >a){ break; }else{ // 成倍增加,log(n) sum=sum+sum; count=count+count; } } // a減去已增加的sum,res加上count計數。 a=a-sum; res+=count; } if(dividend<0 && divisor>0 || dividend>0 && divisor<0){ return -res; }else{ return res; } } }
注意
為防止溢位,使用long型別。
翻倍。
網上其他方法使用<<1表示 X2,沒有必要這樣做,直接用加法就行,例如sum=sum+sum。