图解LeetCode:Divide Two Integers


这是LeetCode的第29号题目,Divide Two Integers,题目要求计算两个数相除是多少,最后返回整数就可以。

比如给定10和4,那10/4是2;给定7和-3,那么7/(-3)应该返回2,题目要求不能用乘法、除法和取余操作。如果在面试时遇到这个题目该怎么求解呢?

 

我的思路

首先我们可以将除数和被除数都转为正数以简化操作,而对于除法来说其本质上就是减法,比如对于100/4,其本质上无非就是100可以减去多少个4直到剩下数无法再减去4为止,如图所示:

在这里插入图片描述
将右边的1累加最后会得到25,这也就是100/4。

如果让你将上述过程用代码实现应该很简单吧,但是这个算法是在运行起来很慢,假设给定除数是1,被除数是10亿,那么上述算法要运行10亿次,该如何改进呢?

 

算法优化

实际上这个问题的实现思路也就是用减法来模拟除法了,就像上图那样,这里的关键就在于该如何优化这个过程

让我们再来看一下上图的求解过程,每次都简单的减去除数,在这种算法下将被除数减到小于除数是很慢的,该如何加速这个过程呢?仔细想一想。

我们为什么要老老实实的减去一个除数呢?能不能一次多减几个除数?

因此我们每次可以将除数翻倍,直到被除数小于翻倍后的除数为止,此时如果被除数依然大于原始的除数那么继续上述过程,只不过这次除数要从初始值开始翻倍,还是以100/4为例,如图所示:

在这里插入图片描述

由于除数每次翻倍,这样上述过程可以快速的计算完毕,然后再讲右边的计数累加,算一下,1+2+4+8+1+2+4+1+2同样是25。

有的同学可能会有疑问,为什么每次除数都翻倍而不是x3呢,不要忘了题目要求不可以使用乘法,翻倍可以简单的将该数的二进制左移一位得到,这样我们可以在不是用乘法的操作下模拟除法了。

有了这些分析代码还会很难实现吗?

 

代码实现

该代码仅仅就是将上图的计算过程翻译成C++代码,唯一需要注意的一点是溢出情况的处理。

int divide(int dividend, int divisor) {
    int sign = (dividend^divisor)>=0?1:-1;
    long int a = dividend;
    long int b = divisor;
    a = a>0?a:-a;
    b = b>0?b:-b;
    long int t = b;
    long int r = 0;
    long int i = 1;
    while(a-b>=0){
        a-=t;
        r+=i;
        i=(i<<1);
        t=(t<<1);
        if (a-t<0){
            i=1;
            t=b;
        }
    }

    if (sign<0&&(-r)<(int)0x80000000 ||
       sign>0&&r>(int)0x7fffffff)
      return 0x7fffffff;
    return sign>0?r:(-r);
}

 

总结

这个题目的难点不在于思路,关于在于基于该思路的优化,实际上这个题目的优化在思想上和二分查找有些类似,二分查找的思想是每次排除掉一半的数据量从而加快查找速度,而这里是每次将除数翻倍从而加快收敛速度,因此如果你真的深刻理解了二分查找的话,那么这个问题对于来说应该不在话下。

更多计算机内功文章,欢迎关注微信公共账号:码农的荒岛求生

在这里插入图片描述
彻底理解操作系统系列文章
1,什么程序?
2,进程?程序?傻傻分不清
3,程序员应如何理解内存:上篇
4,程序员应如何理解内存:下篇
 

计算机内功决定程序员职业生涯高度

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值