《剑指offer》面试题1:整数的除法

题目:

输入两个int型整数,它们进行除法计算并返回商,要求不得使用乘号'*'、除号'/'以及求余符号'%'。当发生溢出时,返回最大的整数。假设除数不位0。例如,输入15,2,输出15/2的结果,即7。

分析:

  • 首先要解决符号的问题,我们可以用减法来实现除法。例如15/2的商,可以用15不断减去2,当减去7个2的时候余数是一,所以商就是7。

  • 如果给的被除数很大但是除数很小的话,用着样的方法会造成时间复杂度为O(n)。我们可以对其进行优化,当被除数大于除数时,继续比较判断被除数是否大于除数的2倍,如果是继续判断是否大于除数的4倍、8倍等。如果被除数最多大于除数的2的次幂那先减去除数2^k次幂,然后再重复前面的步骤。因为每次除数翻倍所以时间复杂度为O(log n)。

  • 基于题目没有告知所给的数是否都是整数,所以还要考虑正负号不相同的情况,如果有负数我们可以先把它转成正数,计算后再调正结果的正负号

  • 但是将负数转成正数会有一个小问题,如果将-2^31次幂转换成正数会导致溢出,所以我们把正数都转成负数就不会有这样的问题了

  • 最后还有一个特殊情况就是如果将-2^31/-1得到2^31超过了int的最大范围2^31-1导致溢出,所以如果是这种情况我们单独处理。

    代码实现:

    public int divide(int dividend, int divisor){
            if(dividend==0x80000000 && divisor==-1){//特殊情况
                return Integer.MAX_VALUE;
            }
            int negative=2;
            if(dividend >0){//将被除数转换成负数
                negative--;
                dividend=-dividend;
            }
            if(divisor >0){//将除数转换成负数
                negative--;
                divisor=-divisor;
            }
            int result =divideCore(dividend,divisor);//调用divdiecore方法产生结果
            return negative==1 ? -result :result;//判断时输出正的还是负的结果
    ​
        }
        private int divideCore(int dividend, int divisor){
            int result=0;
            while(dividend<=divisor){//除数一直减去被除数,直到被除数大于除数
                int value=divisor;//被减去的总和
                int quotient=1;//商
                while(value>=0xc0000000 &÷nd<=value+value){//如果总和小于最大值的一半并且除数小于总和的两倍
                    quotient +=quotient;
                    value +=value;
                }
                result +=quotient;//结果加上这一次的商
                dividend -=value;//被除数减去这次被减去的总和
            }
            return result;
        }

    0x80000000为最小int整数,0xc0000000是它的一半

你可能感兴趣的:(剑指offer,算法,数据结构)