29. 两数相除

题目描述

给定两个(整数),被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
被除数和除数均为32位有符号整数。除数不为 0。假设我们的环境只能存储32位有符号整数,其数值范围是 [−2^31,  2^31 − 1]。本题中,如果除法结果溢出,则返回 2^31 − 1

方法1

思路

因为要求不使用乘除,mod运算,我们可以思考使用加减或者位运算
缺点:时间复杂度为O(n),这里n为问题要求的结果:商n,当被除数很大、除数很小时,效率非常低(比如,dividend = INT_MAX,divisor=1)这个算法会超时,所以我们要试着在这个算法的基础上,分析此算法的瓶颈所在,进行优化,把复杂度降下来,一般o(n)的复杂度,我们要首先看一看能不能往O(logn)方向进行优化.

代码实现

class Solution {
public:
    int divide(int dividend, int divisor) {
        //溢出的情况
        if(divisor==0 || (dividend==INT_MIN && divisor==-1))
            return INT_MAX;
        if(dividend == 0)
            return 0;
        int sign = ((dividend<0) ^ (divisor<0)) ? -1 : 1;
        //C库函数 long int labs(long int x)返回x的绝对值
        long a = labs(dividend);
        long b = labs(divisor);
        int ret = 0;
        while(a >= b) 
        {
        	a = a-b;
            //商等于循环能进行的减法操作的计数值
        	ret = ret+sign;
        }
        return ret; 
    }
};

方法2

思路

直接求出商的二进制表示的各个位的值

 a = (q_0*2^0+q_1*2^1+q_2*2^2+...+q_i*2^i)*b+r
 a-q_i*2^i*b = (q_0*2^0+q_1*2^1+q_2*2^2+...+q_(i-1)*2^(i-1))*b+r

这里q_i的值为0或者1,注意:我们必须从高位到低位逐位试探(例如把7表示为二进制表示一样,需要从最高位开始试探)

代码实现

 */
class Solution {
public:
    int divide(int dividend, int divisor) {

    	if(divisor==0 || (dividend==INT_MIN && divisor==-1))
            return INT_MAX;
        if(dividend == 0)
            return 0;
        int sign = ((dividend<0) ^ (divisor<0)) ? -1 : 1;
        //C库函数 long int labs(long int x)返回x的绝对值
        long a = labs(dividend);
        long b = labs(divisor);
        long ret = 0;
        for(int i=31; i>=0;i--) 
        {   //即a >= (2^i)*b
            if(a >= b<<i) 
            {
                ret = ret | (1<<i);
                a-=b<<i;
            }
        }
        return sign==1?ret:-ret;        
    }
};

方法3

思路

和上面的思路本质上一样,不过上面使用了位运算的方式,这里使用了加减法的方式,将商的二进制表示的分解值都求出来相加。

代码实现

*/
class Solution {
public:
    int divide(int dividend, int divisor) {

        if(divisor==0 || (dividend==INT_MIN && divisor==-1))
            return INT_MAX;
        if(dividend == 0)
            return 0;
        int sign = ((dividend<0) ^ (divisor<0)) ? -1 : 1;
        long a = labs(dividend);
        long b = labs(divisor);
        long ret = 0;
        while(a >= b) 
        {
            long temp = b;
            //temp和multiple变量的值和状态保持一致
            long multiple = 1;
            //这里的条件判断中使用了temp << 1的方式,是为了
            //在跳出循环时temp的值为破坏条件的前一个状态
            while(a >= (temp << 1))
            {
                temp <<= 1;
                multiple <<= 1;
            }
            a -= temp;
            ret += multiple;
        }
        return sign==1?ret:-ret; 
    }
};

posted on 2021-05-02 07:15  朴素贝叶斯  阅读(308)  评论(0编辑  收藏  举报

导航