LintCode 414. Divide Two Integers (Binary Search经典题!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/roufoo/article/details/87094850
  1. Divide Two Integers

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

If it will overflow(exceeding 32-bit signed integer representation range), return 2147483647

Example
Example 1:

Input: dividend = 0, divisor = 1
Output: 0
Example 2:

Input: dividend = 100, divisor = 9
Output: 11

代码如下:
这题的解法还是基于binary search。

  1. 每次shift<<1,直到dividend < (divisor<<shift)然后dividend -= (divisor << (shift - 1)); 如此往复,直到dividend < divisor;
  2. 一定要记得用long long。
    如果不用long long,此题有无数陷阱:
    a) isNegative也可以用 dividend * divisor < 0 来判断(不过此题不允许用乘法)。但乘积很可能超过INT_MAX或INT_MIN。如果用(long long) (dividend * divisor) < 0也不对,因为dividend * divisor本身就越界了。必须用 (long long)dividend * divisor
    b) 如果dividend = -2147483648, divisor = -1,除下来等于2147483648 > 2147483647 已经越界。可以专门针对这种情况处理。
    c) 如果dividend和divisor有负数,不能仅仅加个负号就将其变正。因为它们可能等于-2147483648,加负号又越界。
    d) 在while ((divisor << shift) <= dividend) {
    shift++;
    }
    这里当shift大到一定程度,divisor<<shift可能等于2147483648,这样又越界,实际还是负数(=-2147483648),所以还是小于dividend! 这个bug很难发现!
    顺便说一下为什么2147483648实际上是存的-2147483648呢?
    因为
    2147483647 = 01111111 11111111 11111111 11111111
    -2147483647表示为(2的补码)
    10000000 00000000 00000000 00000001
    -2147483648(2的补码)还可以比-2147483647少1,所以是
    10000000 00000000 00000000 00000000
    另外,实际上补码的补码就是原码(数的原始表示)
    所以10000000 00000000 00000000 00000000 的补码是
    11111111 11111111 11111111 11111111 + 1,第一个1是负号,所以
    1111111 11111111 11111111 11111111 + 1 = 10000000 00000000 00000000 00000000=2147483648,这里第一个1是实际数字。加上负号,即-2147483648。
class Solution {
public:
    /**
     * @param dividend: the dividend
     * @param divisor: the divisor
     * @return: the result
     */
    int divide(int dividend, int divisor) {
        if (divisor == 0) return INT_MAX;
        if (dividend == INT_MIN && divisor == -1) return INT_MAX;  //important! 
        if (dividend == 0) return 0;
        
       // bool isNegative = (((long long)dividend * divisor) > 0) ? false : true; //remember to use long long! Otherwise overflow (case: 2147483647 2)
        bool isNegative = ((dividend < 0) && (divisor > 0)) || ((divisor < 0) && (dividend > 0));
        
        long long dividendll = (long long)dividend, divisorll = (long long)divisor;
        if (isNegative) {
            if (dividendll < 0) dividendll = -dividendll; //note! it is incorrect for case dividend ==  -2147483648
            else divisorll = -divisorll;
        } else if (dividendll < 0) {
            dividendll = -dividendll;
            divisorll = -divisorll;
        }
        int quotient = 0;
        
        while(dividendll >= divisorll) {
            int shift = 1;
            while ((divisorll << shift) <= dividendll) {
                shift++;
            }
            quotient += 1 << (shift - 1);
            dividendll -= (divisorll << (shift - 1));
        }
        
        return quotient * (isNegative ? -1 : 1);    
    }
};

猜你喜欢

转载自blog.csdn.net/roufoo/article/details/87094850
今日推荐