[LeetCode#29]Divide Two Integers

The problem:

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

If it is overflow, return MAX_INT.

My analysis:

The idea behind this problem is very veyr elegant, it involves important mainpulataion over the digits of a number, you must master it! And this kind of problem always involves a lot of conner cases, you should be very very careful!!
The key idea:
solution 1: We keep on substracting divisor from dividend, and we record the times of substraction. Once we reach a value less than divisor, we return the count. The time complexity of this solution is O(n). 
solution 2: It also uses the idea of substraction. But it substracts in a more brave way.
num = a_0 * 2^0  +  a_1 * 2^1 + a_2 * 2^2 + a_3 * 2^3 + a_4 * 2^4 + a_5 * 2^5
Idea:
2.1 We left shift divisor to reach the value just less(or equal than) dividend. 
while (divisor <= (dividend >> 1)) { //note we stop value just bigger than (dividend >> 1), cause we would stract it. 
    divisor <<= 1;
    digit++;
}
2.2 Then we follow the below invariant.
Iff dividend larger than divisor, it means we could substract divisor from dividend. And we should add the substracted parts into the return value: 
if (dividend >= divisor ) {
    ret += (1 << digit); 
    dividend -= divisor;
}
Note: the digit here is used to record the current divisor's left shift. it represent (1>>digit) times of original divisor.
Then we could test number less than divisor (with lower times of divisor), by decreasing digit by one and right shift divisor one digit. 
digit--;
divisor >>= 1;
Note: digit is useds to record how many times the current divisor of the original divisor. And divisor is the actual number we opearte on. 
while (digit >= 0) {
    if (dividend >= divisor ) {
        ret += (1 << digit);
        dividend -= divisor;
    }
    digit--;
    divisor >>= 1;
}

Some tricky skills: 
1. the sign of two numbers' product or divide. 
boolean is_neg = (dividend ^ divisor) >>> 31 == 1;
">>>" respresent we right shift the number 31 digits and fill those shifted digits with 0. 

2. inorder to make the uniform comparsion when we shift digits. (and the sign only affects the result's sign, not the abs () part.) We need to use the abs value of dividend and divisor in computation. To get the abs value, we shoul consider following corner cases:
2.1 divisor is 0, we return Integer.MAX_VALUE. 
if (divisor == 0)
    return Integer.MAX_VALUE;
    
2.2 dividend is Integer.MIN_VALUE(the abs() over it would result in overflow). we could substract it with divisor's abs value at first, thus we would not overflow.
if (dividend == Integer.MIN_VALUE) {
    dividend += Math.abs(divisor);
    if (divisor == -1) //note this corner case.
        return Integer.MAX_VALUE;
    ret ++; //rember to record the substraction in the result. 
}

2.3 iff the divisor is Integer.MIN_VALUE. 
2.3.1 iff the dividend is also Integer.MIN_VALUE, we should return 1;
2.3.2 iff the dividend is a Integer larger than Integer.MIN_VALUE, we should return 0. 
int ret = 0;
if (dividend == Integer.MIN_VALUE) {
    dividend += Math.abs(divisor);
    if (divisor == -1)
        return Integer.MAX_VALUE;
    ret ++;
}
if (divisor == Integer.MIN_VALUE) {
    return ret;
}
Note the logic at here is very elegant. 

The solution:

public class Solution {
    public int divide(int dividend, int divisor) {
        if (divisor == 0)
            return Integer.MAX_VALUE;
        boolean is_neg = (dividend ^ divisor) >>> 31 == 1;
        int digit = 0;
        int ret = 0;
        if (dividend == Integer.MIN_VALUE) {
            dividend += Math.abs(divisor);
            if (divisor == -1)
                return Integer.MAX_VALUE;
            ret ++;
        }
        if (divisor == Integer.MIN_VALUE) {
            return ret;
        }
        divisor = Math.abs(divisor);
        dividend = Math.abs(dividend);
        while (divisor <= (dividend >> 1)) {
            divisor <<= 1;
            digit++;
        }
        while (digit >= 0) {
            if (dividend >= divisor ) {
                ret += (1 << digit);
                dividend -= divisor;
            }
            digit--;
            divisor >>= 1;
        }
        return is_neg ? -1 * ret : ret; 
    }
}
原文地址:https://www.cnblogs.com/airwindow/p/4289573.html