leetcode 算法题解之 Divide Two Integers

问题描述

Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.

问题本身很简单,就是不用乘除法和求余运算,完成简单的整数除法。(如果溢出,就返回 INT_MAX就好)。

思路1 – 原始思路

问题看起来很简单,我们只需要沿用整数除法的定义,逐次累加除数直至其刚好大于或者等于被除数 – 除数,结果就一目了然了。
当然这里说的是除数和被除数都是正整数的情况,那么当有一方或者两方为负数的时候,问题就不能简单这么解决了,不过也只需要存储一个两个运算成员符号的异或结果sign,最后输出的时候 return sign ? result : -result 这样也就解决了。

上面说的思路,简单累加的话,就是一个O(N)的平均复杂度,对于某些问题来说,O(N)的复杂度完全是可以接受的,然而对于一个本来只需要一条 CPU 指令就可以搞定的问题来说,做成这个复杂度也实在是令人恼火。

不过还是先把代码写出来吧,看看能不能AC:

class Solution {
public:
    int divide(int dividend, int divisor) {
        if(!divisor || (dividend == INT_MIN && divisor == -1))
            return INT_MAX;
        if(!dividend)
            return 0;
        int result = 0, sum = 0;
        bool sign = bool(dividend < 0) == bool(divisor < 0);
        unsigned long long dividendabs = labs(dividend);
        unsigned long long divisorabs = labs(divisor);
        while(1) {
            sum += divisorabs;
            result ++;
            if(sum == dividendabs)
                break;
            else if(sum > dividendabs) {
                result --;
                break;
            }
        }
        return sign ? result : -result;
    }
};

果然毫无意外的 TLE了(Time Limit Exceeded)。TLE的测试例是-2147483648,1。诚然这个问题完全可以在入口值判断那里解决,然而如果测试例是2147483646,1 呢?估计也会超时吧。所以问题还是要从时间复杂度这个问题上解决。

思路2-跑快一点

直观地分析这个问题,看起来问题主要还是出在向结果靠近的速度太慢,如果我们不是线性地累加呢?如果我们每次都翻倍……?根据经验,一旦用这种方式接近,往往可以让问题降低到 O(logn) 的程度。
让我们换个思路,每个整数都能转化成若干个2的n次方之和,这种数则一共是log2(N)个,若是从最低位找起,则平均每次运行log2(N)/2次,就可以啦。
根据 divisor = dividend * result = dividend * (这些数之和),问题就可以解决啦~!而复杂度则正好是O(log(N) * log(N))
下面上代码:

class Solution {
public:
    int divide(int dividend, int divisor) {
        if(!divisor || (dividend == INT_MIN && divisor == -1) || (dividend == INT_MAX && divisor == 1))
            return INT_MAX;
        if(!dividend)
            return 0;
        int result = 0, sum = 0;
        bool sign = bool(dividend < 0) == bool(divisor < 0);
        long long dividendabs = labs(dividend);
        long long divisorabs = labs(divisor);
        while(divisorabs <= dividendabs) {
            long long temp = divisorabs, doubles = 1;
            while((temp << 1) <= dividendabs) {
                temp <<= 1;
                doubles <<= 1;
            }
            dividendabs -= temp;
            result += doubles;
        }
        return sign ? result : -result;
    }
};

最后AC了,结果嘛,还不错(逃

    原文作者:cunfate
    原文地址: https://www.jianshu.com/p/982d1f0ea98d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞