題目ide
Divide two integers without using multiplication, division and mod operator.post
If it is overflow, return MAX_INTspa
連接.net
https://leetcode.com/problems/divide-two-integers/3d
答案code
1、int的最大值MAX_INT爲power(2,31)-1 = 2147483647blog
2、int的最小值MIN_INT爲-power(2,31) = -2147483648ip
3、當MIN_INT除以-1的時候,發生溢出,由於獲得的值大於MAX_INTleetcode
4、有符號數的最高位爲1時,表示負數,因此可使用異或運算得到商的符號rem
5、abs的各類版本看這裏,double abs(double),long abs(long)居然在C++中有,其實我想本身寫個求絕對值方法的,不過,手抖仍是搜了一下abs的原型。
6、這纔是重中之重,剛開始看到題目,我不知道怎麼用位運算去實現除法,先搜到答案
而後思考其中的原理,爲何能夠這麼作,思考以後本身才寫了代碼。
個人推理以下,若有問題,請指出,謝謝。下面我有^表示指數,不要跟C++中的^弄混了。
a = b * x (x爲要求的商,等號應該爲約等於,其實嘛,應該是a >= b * x && a < b * (x+1))
任何一個整數是能夠用二進制表示的,因此x=2^m + 2^n + ...... + 2^t,其中m > n > t,m,n,t爲整數。
x還能夠這麼表示x = 1*2^m + 0 * 2^(m-1) + 1 * 2^(m-2) + ...... + (1或0)*2^0。
事實上x還能夠這麼表示:
x = (2^k + 2^(k-1) + ...... + 2^0) + (2^t + 2^(t-1) + ...... + 2^0) + ...... + (2^r + 2^(r-1) + ...... + 2^0),其中k > t > ...... > r。
因此 a = b * (2^k + 2^(k-1) + ...... + 2^0) +b * (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0).
而且k,t,r等知足如下關係:
b * (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0) < b * (2^k + 2^(k-1) + ...... + 2^0)
...... + b * (2^r + 2^(r-1) + ...... + 2^0) < b * (2^k + 2^(k-1) + ...... + 2^0) - b * (2^t + 2^(t-1) + ...... + 2^0)
第一次是 a - b * (2^k + 2^(k-1) + ...... + 2^0) = b * (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0)
對b進行不斷左移,即上式的橙色部分,而並累加位移(2^x')是x的一部分,將a不斷減去不斷左移後的b,便可獲得等式左邊的數據。
a - b * (2^k + 2^(k-1) + ...... + 2^0) < b * (2^k + 2^(k-1) + ...... + 2^0)
即b * (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0) < b * (2^k + 2^(k-1) + ...... + 2^0)
這個是必然成立的,若是不成立,則b還能夠繼續左移,即k的值要比當前達到的k還要大,故每次a處理後的結果會比b處理後的結果要小。
第二次是a - b * (2^k + 2^(k-1) + ...... + 2^0) - b * (2^t + 2^(t-1) + ...... + 2^0) = ...... + b * (2^r + 2^(r-1) + ...... + 2^0)
藍色部分爲第一次的結果。
推到這裏,你們應該懂了
代碼
1 class Solution { 2 public: 3 static const int MAX_INT = 2147483647; 4 static const int MIN_INT = -2147483648; 5 6 int divide(int dividend, int divisor) { 7 if(dividend == MIN_INT && divisor == -1) 8 { 9 return MAX_INT; 10 } 11 12 long pre = abs((long)dividend); 13 long post = abs((long)divisor); 14 int index; 15 int rem = 0; 16 17 while(pre >= post) 18 { 19 long tmp = post; 20 for(index = 0; pre >= tmp; index ++, tmp <<= 1) 21 { 22 pre -= tmp; 23 rem += (1 << index); 24 } 25 } 26 27 return (dividend >> 31) ^ (divisor >> 31) ? -rem:rem; 28 } 29 };