Leetcode 两数相除

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

返回被除数 dividend 除以除数 divisor 得到的商。

输入: dividend = 10, divisor = 3
输出: 3
输入: dividend = 7, divisor = -3
输出: -2

说明:

被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231,  231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。

 

题解思路:

首先题目中规定只能使用32位有符号整数,且不能使用乘法、除法和mod运算符。

思路一:暴力循环,不可取,会不满足时间复杂度。

思路二:首先要考虑退化的情况:

              若 dividend = INT_MIN, divisor = -1 则商会正溢出;

              若dividene=INT_MIN,divisor=INT_MIN,则返回1;

              若divisior = 1,可直接返回 dividend;

              若divisor = -1,则返回 dividend-dividene-dividend (通过减法来取相反数)

              另外,我们先通过比较除数和被除数的符号来确定商的符号,为了运算方便,统一情况,则把被除数和除数统一转化为

              负数,这样便可用被除数减去除数来执行循环运算。首先我们采取除数逐渐倍增的方法来减少循环次数,这样可以达到                O(logn+r) 级别的时间复杂度,远远低于线性复杂度。定义当前除数的倍数为 times,当前除数为div, 被除数为                              dividend。循环内情况可分为三种:

                              1.若 dividend-div>0 且 div=divosor,则意味着被除数绝对值已经小于初始除数了,则此时可以退出循环

                              2.若 dividend-div>0 但 div != divosor,则意味着被除数绝对值已经小于当前除数,所以应该将当前除数缩小                                     一倍,并进行下一轮循环

                              3.若 dividend-div<0 则意味着被除数绝对值大于当前除数,还没有除尽,所以为了增加效率,应该将dividend                                   更新后,对div进行加倍,进入下一轮循环。(但要注意,每次对div加倍的时候应该不能小于INT_MIN)

代码如下:

class Solution {

public:

    int divide(int dividend, int divisor) {

        if(dividend== INT_MIN && divisor== INT_MIN) return 1;

        if (dividend == INT_MIN && divisor == -1) return INT_MAX;

        if(divisor== 1 ) return dividend;

        if(divisor==-1 ) return dividend-dividend-dividend;

        int ans=0;

        int op;

        if((dividend>0 && divisor >0 ) || (dividend<0 && divisor<0)) op=1;

        else op=0;

        if(dividend>0) dividend= dividend-dividend-dividend;

        if (divisor>0) divisor= divisor-divisor-divisor;

        int times=1;

        int div=divisor;

        while(true)

        {

            if(dividend-div>0 && div==divisor) break;

            else if (dividend-div>0 && div!=divisor)

            {

                div>>=1;

                times>>=1;

            }

            else

            {

                ans+=times;

                dividend-=div;

                if(INT_MIN-div<div)

                    {

                        times+=times;

                        div+=div;

                    }

                

            }                                              

        }

        if (op) return ans;

        else return ans-ans-ans;

       }

};

          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值