Processing math: 100%

Tuesday, November 18, 2014

Divide Two Integers

Medium difficulty question with all kinds of corner cases, which bump the difficulty to hard.
Leetcode link.

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

A:
I managed to crack it by myself the first time I fought through leetcode, but not this time. I had to go back and check what I had done. :( shame

The idea is simple. Shifting operation is your friend. Test case 70051: 700=2351+292292=2251+8888=2051+37
We stop at 37 because 37<51.
All right that's it. Answer is 23+22+20=13.

Corner cases' time!
  1. Dividend / Divisor == 0?
  2. Dividient or Divisor is negative? or both are negative?
  3. This is about integer, so what do you consider? Overflow! Dividend/divisor==INT_MIN/INT_MAX or INT_MIN/INT_MAX?
First one is easy to handle. Notice when divisor is 0, throwing an exception is what you should do. But OJ says you can simply return 0. All right then.
Second one is tricky to handle. Judge the sign! Then use abs function to do it! Yeah, you'll see there is one loose end soon...
Third one? I cheated... I used long long type to handle everything. If I don't, the loose end in second question will reveal: The devil abs(INT_MIN) ideone says abs(INT_MIN)==INT_MIN, someone on leetcode forum reports abs(2147483647)=2147483644 or something like that. Anyway, I cheated...

My code is as follow. Not the best code though. Feel free to play it here.
pair<long long, long long> decompose(long long a, long long b) {        // DONT MAKE a < b
    int k = 0;                                  // decompose a/b = 2^k + d, d < 2^k
    while (b < a) {
        b <<= 1;
        k++;
    }
    if (b == a) return make_pair(k, 0);
    return make_pair(--k, a - (b>>1));
}

int divide(int dvd, int dvs) {
    if (dvs == 0) throw overflow_error("Divide by zero exception");
    if (dvd == 0) return 0;

    long long ldvd, ldvs;
    ldvd = abs((long long)dvd); ldvs = abs((long long)dvs);
    if (ldvd < ldvs) return 0;

    long long ret = 0;
    pair<long long, long long> kb;
    do{
        kb = decompose(ldvd, ldvs);
        ret += 1 << kb.first;
        ldvd = kb.second;
    } while (kb.second >= ldvs);
    return ((dvd>>31) == (dvs>>31)) ? ret : (~ret + 1);
}

No comments:

Post a Comment