Saturday, April 19, 2014

LeetCode: Divide Two Integers

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


The divide operation can be simulated by subtraction. Use the dividend to subtract divisor each time until the result comes negative. And we can times the divisor by 2 each time to boost the subtraction.

C++ Code:

/*
 * func: divide
 * goal: divide two integers without using mulitiplication, division and mode operator
 * @param dividend
 * @param divisor
 * return: the result
 */
int divide(int dividend, int divisor){
    if(dividend == 0){
        return 0;
    }
    if(divisor == 0){
        throw std::invalid_argument("INVALID DIVISOR");
    }

    long long new_dividend = dividend >= 0 ? static_cast<long long>(dividend) : -static_cast<long long>(dividend);
    long long new_divisor = divisor >= 0 ? static_cast<long long>(divisor) : -static_cast<long long>(divisor);
        
    long long ret = 0;
    while (new_dividend >= new_divisor) {
        long long current_divisor = new_divisor;
        for (int i = 0; new_dividend >= current_divisor; ++i, current_divisor <<= 1) {
            new_dividend -= current_divisor;
            ret += 1 << i;
        }
    }
    //we right shift 31 bits to get the sign bit
    return static_cast<int>(((dividend^divisor)>>31) ? (-ret) : (ret));
}

There is a really weird thing when I tried to submit. Before doing the division, the dividend and divisor had to be casted to long numbers. But that doesn't work if I casted them to long, the system will show time limit exceeded. When I casted them to long long, it works well. But if fact, there should be no difference between long type and long long type, both of which will take 8 bytes.

Python Code:

# func: Divide two integers without using multiplication, division and mod operator.
# @param dividend:
# @param divisor:
# @return:
def divide(dividend, divisor):
    if divisor == 0:
        return None
    #if 3/4 return 0, if -3/4 return -1
    if abs(dividend) < abs(divisor):
        return 0
    #common case
    else:
        new_dividend = abs(dividend)
        new_divisor = abs(divisor)
    
        new_divisor <<= 1
        result = 2
        #keep left shifting until divisor is larger than dividend
        while new_dividend >= new_divisor:
            new_divisor <<= 1
            result <<= 1
    
        #add remaining part
        new_divisor >>= 1
        result >>= 1
        final_result = 0
        while new_dividend >= abs(divisor):
            if new_dividend >= new_divisor:
                new_dividend -= new_divisor
                final_result += result
    
            new_divisor >>= 1
            result >>= 1
    
        if (dividend > 0 and divisor > 0) or (dividend < 0 and divisor < 0):
            return final_result
        else:
            return 0-final_result

No comments:

Post a Comment