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 }
注意:
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 }
简化一点:
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 }
GitHub Code:
Ref: http://blog.csdn.net/fightforyourdream/article/details/16899675