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

posted on 2014-10-24 20:15  Yu's Garden  阅读(3242)  评论(1编辑  收藏  举报

导航