LeetCode: Divide Two Integers 解題報告


Divide Two Integers


Divide two integers without using multiplication, division and mod operator.

SOLUTION 1
1. 基本思想是不斷地減掉除數,直到為0為止。但是這樣會太慢。

2. 我們可以使用2分法來加速這個過程。不斷對除數*2,直到它比被除數還大為止。加倍的同時,也記錄下cnt,將被除數減掉加倍后的值,並且結果+cnt。

因為是2倍地加大,所以速度會很快,指數級的速度。

3. 另外要注意的是:最小值的越界問題。對最小的正數取abs,得到的還是它。。。 因為最小的正數的絕對值大於最大的正數(INT)

所以,我們使用Long來接住這個集合就可以了。

 1 public class Solution {
 2     public int divide(int dividend, int divisor) {
 3         long a = Math.abs((long)dividend);
 4         
 5         // ref : http://blog.csdn.net/kenden23/article/details/16986763
 6         // Note: 在這里必須先取long再abs,否則int的最小值abs后也是原值
 7         long b = Math.abs((long)divisor);
 8         
 9         int ret = 0;
10         // 這里必須是= 因為相等時也可以減
11         while (a >= b) {
12             // 判斷條件是 >=
13             for (long deduce = b, cnt = 1; a >= deduce; deduce <<= 1, cnt <<= 1) {
14                 a -= deduce;
15                 ret += cnt;
16             }
17         }
18         
19         // 獲取符號位。根據除數跟被除數的關系來定
20         return (dividend > 0) ^ (divisor > 0) ? -ret: ret;
21     }
22 }
View Code

注意:

1. C,java中的右移運算,是帶符號位的,叫算術右移http://www.cppblog.com/tx7do/archive/2006/10/19/13867.html

2015.1.3 redo:

Leetcode又加強了一大堆邊界條件運算,所以我們代碼也要更改:

1. 返回值的時候,判斷是不是越界,越界返回最大值。

例子:

Input: -2147483648, -1
Expected: 2147483647

 1 public int divide(int dividend, int divisor) {
 2         if (divisor == 0) {
 3             return Integer.MAX_VALUE;
 4         }
 5         
 6         // Note: 在這里必須先取long再abs,否則int的最小值abs后也是原值
 7         long dividendTmp = Math.abs((long)dividend);
 8         long divisorTmp = Math.abs((long)divisor);
 9         
10         // bug 3: ret should use Long to avoid overflow.
11         long ret = 0;
12         // bug 2: should use dividentTmp > divisor as the while judge.
13         while (dividendTmp >= divisorTmp) {
14             // bug 1: should use Long for tmp.
15             long tmp = divisorTmp;
16             int rst = 1;
17             while(tmp <= dividendTmp) {
18                 // bug 3: the two statement should inside the while LOOP.
19                 ret += rst;
20                 dividendTmp -= tmp;
21                 
22                 tmp <<= 1;
23                 rst <<= 1;
24             }
25         }
26         // bug 4: out of range:
27         /*
28         Input:    -2147483648, -1
29         Output:    -2147483648
30         Expected:    2147483647
31         */
32         //ret = ((dividend > 0) ^ (divisor > 0)) ? -ret: ret;
33         ret = ((((dividend ^ divisor) >> 31) & 1) == 1) ? -ret: ret;
34         
35         if (ret > Integer.MAX_VALUE || ret < Integer.MIN_VALUE) {
36             return Integer.MAX_VALUE;
37         } else {
38             return (int)ret;
39         }
40     }
View Code

簡化一點:

 1 public int divide(int dividend, int divisor) {
 2         long a = Math.abs((long)dividend);
 3         long b = Math.abs((long)divisor);
 4         
 5         long ret = 0;
 6         
 7         while (a >= b) {
 8             for (long tmp = b, cnt = 1; a >= tmp; tmp <<= 1, cnt <<= 1) {
 9                 ret += cnt;
10                 a -= tmp;
11             }
12         }
13         
14         ret = (((dividend ^ divisor) >> 31) & 1) == 1 ? -ret: ret;
15         if (ret > Integer.MAX_VALUE || ret < Integer.MIN_VALUE) {
16             return Integer.MAX_VALUE;
17         }
18         
19         return (int)ret;
20     }
View Code

 

GitHub Code:

divide.java

 

Ref: http://blog.csdn.net/fightforyourdream/article/details/16899675


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM