[LeetCode]problem 29. Divide Two Integers

TAG

位操作二分查找?除法就是被除数包含多少个除数

题目链接

方法

没有思路,直接看得DISCUSS,写得太好了。

Detailed Explained 8ms C++ solution

首先,dividend是被除数,divisor是除数;

接着,除法表示被除数中有多少个除数,所以在不让使用乘法、模运算的情况下,我们使用位操作来以2倍的速度增大除数,直到再增大就要大于被除数了。那么此时我们能够直到除数增大了多少倍,那么就是其中包含多少个除数。其个数就是除法的结果。当然,此时还没有除尽,所以用当前被除数减去该增大的除数,并开始下次循环,直到被除数小于除数为止。

由于除数二倍形式增大,并通过减法、再重新增大来不断逼近最后的结果,其过程有些类似二分查找。

最后,溢出情况:

  1. 除数为0

  2. 被除数为INT_MIN , 而除数为-1, 其结果为 INT_MAX + 1 , 超过了int的范围,故溢出。

代码

class Solution {
public:
    int divide(int dividend, int divisor) {
        if( divisor == 0
            || ( dividend == numeric_limits<int>::lowest() && divisor == -1 )
          )
        {
            return numeric_limits<int>::max();
        }
        bool isPositive = ( dividend > 0 ) == ( divisor > 0) ;
        unsigned dividendU = abs(static_cast<long long>(dividend));
        unsigned divisorU = abs(static_cast<long long>(divisor)); // just in case INT_MIN , and `unsigned` can store it safely

        int result = 0 ;
        while(dividendU >= divisorU)
        {
            int nrBitMoved = 0 ;
            unsigned movedDivisor = divisorU;
            while(dividendU >= movedDivisor && ! isOverflowAfterMove(movedDivisor))
            {
                movedDivisor <<= 1;
                ++nrBitMoved;
            }
            if(dividendU >= movedDivisor)
            {
                // movedDivisor will overflow
                dividendU -= movedDivisor;
                result += ( 1 << nrBitMoved );
            }
            else
            {
                // movedDivisor is bigger
                movedDivisor >>= 1;
                --nrBitMoved;
                dividendU -= movedDivisor;
                result += ( 1 << nrBitMoved );
            }
        }
        return isPositive ? result : -result;
    }
private :
    bool isOverflowAfterMove(unsigned num)
    {
        // if the highest bit is 1 , then after left move , it will overflow
        return ( (num >> (sizeof(num) * 8 - 1)) == 1 ) ;
    }
};

后记

首先,abs在C++11下有3个重载,分别对int, long , long long . 此外,还有labs, llabs.

然后,代码中我检测了增大的除数是否有可能溢出。加上后面的if判断,这可能导致了我的代码效率不高。这对于我的代码是必须的!因为如果一贯增大除数的确有可能溢出。但是,上面列出的DISCUSS中的代码没有使用溢出检测,其也是对的。因为,他使用的是long long ! 由于被除数的绝对值范围是在unsigned int 之中的,故在long long、且刚好能大于被除数的情况下,其不可能溢出。但是我的代码中使用的是unsigned,故可能溢出。

你可能感兴趣的:(找工作)