码迷,mamicode.com
首页 > 其他好文 > 详细

[LeetCode] Divide Two Integers

时间:2014-11-11 01:57:47      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   ar   os   使用   java   

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

显然,如果光用减法太慢。让商为N,那么需要用O(N)的时间。这里要求比较苛刻,连乘法都不能使用,所以只能寄希望于二进制操作了。

这里可以把除数表示为:dividend = 2^i * divisor + 2^(i-1) * divisor + ... + 2^0 * divisor。这样一来,我们所求的商就是各系数之和了,而每个系数都可以通过移位操作获得。

这里可以分两步走:

1) 获得i的值;

2)将各系数求和。

显然每步都是logN的复杂度。

外还有几个细节需要注意:

1)题目没有说明两个输入都为正数,所以还需要考虑负数。不过这里不用考虑除数为0的情况。

2)在处理时可能发生整数溢出,不光是在增大数的绝对值,另外反号也可能导致溢出, 因为int的范围为[-2147483648, 2147483647],正负两边的最大绝对值是不一样的。最简单的方法是用long去处理。

代码如下:

  1. public int divide(int dividend, int divisor) {  
  2.     boolean positive = (dividend > 0 && divisor > 0)  
  3.             || (dividend < 0 && divisor < 0);  
  4.     long absDividend = Math.abs((long) dividend);  
  5.     long absDivisor = Math.abs((long) divisor);  
  6.   
  7.     int ret = dividePositive(absDividend, absDivisor);  
  8.     return positive ? ret : -ret;  
  9. }  
  10.   
  11. private int dividePositive(long dividend, long divisor) {  
  12.     // The first loop computes i.  
  13.     int i = 0;  
  14.     while (dividend >= divisor << 1) {  
  15.         divisor <<= 1;  
  16.         i++;  
  17.     }  
  18.   
  19.     // The second loop computes the sum of non-zero coefficients.  
  20.     int ret = 0;  
  21.     while (i >= 0) {  
  22.         if (dividend >= divisor) {  
  23.             dividend -= divisor;  
  24.             ret += 1 << i;  
  25.         }  
  26.         divisor >>= 1;  
  27.         i--;  
  28.     }  
  29.   
  30.     return ret;  
  31. }  


另外一种实现可以合并两个循环,边求i的时候,边累加各系数,不过这样没有改变时间复杂度。自己测试了下,发现其实合并循环也不会带来什么实质的性能提升,感觉还是两个循环思路更为清晰。

其实上述方法也可以用递归实现,每次求一个系数,然后对余数进行递归处理。递归代码一般更加精简。

  1. private int dividePositive(long dividend, long divisor) {  
  2.     if (dividend < divisor)  
  3.         return 0;  
  4.   
  5.     int ret = 1;  
  6.     long originalDivisor = divisor;  
  7.     while (dividend >= divisor << 1) {  
  8.         divisor <<= 1;  
  9.         ret <<= 1;  
  10.     }  
  11.   
  12.     return ret + dividePositive(dividend - divisor, originalDivisor);  
  13. }  

 

补充:

有的时候面试题里是允许使用乘号的,那么其实还可以使用二分搜索。这样中思路类似于LeetCode里的Sqrt(x)。这里注意的问题是,对于非 整除的情况,二分搜索要找到最左边那个乘上divisor后小于dividend的数。这个思路其实类似于在sorted array里找insert position。

    1. private int dividePositive(long dividend, long divisor) {  
    2.     long low = 0, high = dividend;  
    3.     long ret = 0;  
    4.     while (low <= high) {  
    5.         long mid = low + (high - low) / 2;  
    6.         long product = mid * divisor;  
    7.         if (product == dividend) {  
    8.             return (int) mid; // Exact match.  
    9.         } else if (product < dividend) {  
    10.             ret = mid; // Cache this result.  
    11.             low = mid + 1;  
    12.         } else { // product > dividend.  
    13.             high = mid - 1;  
    14.         }  
    15.     }  
    16.   
    17.     return (int) ret;  

[LeetCode] Divide Two Integers

标签:style   blog   http   io   color   ar   os   使用   java   

原文地址:http://www.cnblogs.com/yuyanbian/p/4088604.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!