题目

Divide two integers without using multiplication, division and mod operator.

If it is overflow, return MAX_INT

链接

https://leetcode.com/problems/divide-two-integers/

答案

1、int的最大值MAX_INT为power(2,31)-1 = 2147483647

2、int的最小值MIN_INT为-power(2,31) = -2147483648

3、当MIN_INT除以-1的时候,发生溢出,因为得到的值大于MAX_INT

4、有符号数的最高位为1时,表示负数,所以可以使用异或运算获得商的符号

5、abs的各种版本看这里,double abs(double),long abs(long)竟然在C++中有,其实我想自己写个求绝对值方法的,不过,手抖还是搜了一下abs的原型。

6、这才是重中之重,刚开始看到题目,我不知道怎么用位运算去实现除法,先搜到答案

然后思考其中的原理,为什么可以这么做,思考之后自己才写了代码。

我的推理如下,如有问题,请指出,谢谢。下面我有^表示指数,不要跟C++中的^弄混了。

a = b * x (x为要求的商,等号应该为约等于,其实嘛,应该是a >= b * x && a < b * (x+1))

任何一个整数是可以用二进制表示的,所以x=2^m + 2^n + ...... + 2^t,其中m > n > t,m,n,t为整数。

x还可以这么表示x = 1*2^m + 0 * 2^(m-1) + 1 * 2^(m-2) + ...... + (1或0)*2^0。

事实上x还可以这么表示:

x = (2^k + 2^(k-1) + ...... + 2^0) + (2^t + 2^(t-1) + ...... + 2^0) + ...... + (2^r + 2^(r-1) + ...... + 2^0),其中k > t > ...... > r。

所以 a = b * (2^k + 2^(k-1) + ...... + 2^0) +b *  (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0).

并且k,t,r等满足以下关系:

b *  (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0)  < b * (2^k + 2^(k-1) + ...... + 2^0) 

...... + b * (2^r + 2^(r-1) + ...... + 2^0) < b * (2^k + 2^(k-1) + ...... + 2^0)  - b *  (2^t + 2^(t-1) + ...... + 2^0)

第一次是 a - b * (2^k + 2^(k-1) + ...... + 2^0)  = b *  (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0)

对b进行不断左移,即上式的橙色部分,而并累加位移(2^x')是x的一部分,将a不断减去不断左移后的b,即可得到等式左边的数据。

a - b * (2^k + 2^(k-1) + ...... + 2^0)  < b * (2^k + 2^(k-1) + ...... + 2^0)

即b *  (2^t + 2^(t-1) + ...... + 2^0) + ...... + b * (2^r + 2^(r-1) + ...... + 2^0) < b * (2^k + 2^(k-1) + ...... + 2^0)

这个是必然成立的,如果不成立,则b还可以继续左移,即k的值要比当前达到的k还要大,故每次a处理后的结果会比b处理后的结果要小。

第二次是a - b * (2^k + 2^(k-1) + ...... + 2^0) - b *  (2^t + 2^(t-1) + ...... + 2^0) = ...... + b * (2^r + 2^(r-1) + ...... + 2^0)

蓝色部分为第一次的结果。

推到这里,大家应该懂了

代码

 class Solution {
public:
static const int MAX_INT = ;
static const int MIN_INT = -; int divide(int dividend, int divisor) {
if(dividend == MIN_INT && divisor == -)
{
return MAX_INT;
} long pre = abs((long)dividend);
long post = abs((long)divisor);
int index;
int rem = ; while(pre >= post)
{
long tmp = post;
for(index = ; pre >= tmp; index ++, tmp <<= )
{
pre -= tmp;
rem += ( << index);
}
} return (dividend >> ) ^ (divisor >> ) ? -rem:rem;
}
};

leetcode-【中等题】Divide Two Integers的更多相关文章

  1. 乘风破浪:LeetCode真题_029_Divide Two Integers

    乘风破浪:LeetCode真题_029_Divide Two Integers 一.前言     两个整数相除,不能使用乘法除法和取余运算.那么就只能想想移位运算和加减法运算了. 二.Divide T ...

  2. leetcode面试准备:Divide Two Integers

    leetcode面试准备:Divide Two Integers 1 题目 Divide two integers without using multiplication, division and ...

  3. leetcode第28题--Divide Two Integers

    Divide two integers without using multiplication, division and mod operator. 分析:题目意思很容易理解,就是不用乘除法和模运 ...

  4. 【一天一道LeetCode】#29. Divide Two Integers

    一天一道LeetCode系列 (一)题目 Divide two integers without using multiplication, division and mod operator. If ...

  5. [Leetcode][Python]29: Divide Two Integers

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 29: Divide Two Integershttps://oj.leetc ...

  6. LeetCode OJ:Divide Two Integers(两数相除)

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

  7. 【LeetCode】029. Divide Two Integers

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

  8. 【LeetCode】29. Divide Two Integers

    题意:不用乘除求余运算,计算除法,溢出返回INT_MAX. 首先考虑边界条件,什么条件下会产生溢出?只有一种情况,即返回值为INT_MAX+1的时候. 不用乘除求余怎么做? 一.利用减法. 耗时太长, ...

  9. leetcode 中等题(2)

    50. Pow(x, n) (中等) double myPow(double x, int n) { ; unsigned long long p; ) { p = -n; x = / x; } el ...

  10. leetcode 中等题(1)

    2. Add Two Numbers(中等) /** * Definition for singly-linked list. * struct ListNode { * int val; * Lis ...

随机推荐

  1. $.post() 传递多个参数.

    $("#button").click(function() { /获取表单中id为idname和count的文本值付给property的两个属性 var property={&qu ...

  2. win32程序通过LPCREATESTRUCT中的lpCreateParams传递参数给窗口过程函数

    win32窗口程序中如果需要给窗口过程函数传递自定义参数,可以通过LPCREATESTRUCT结构体中的lpCreateParams进行传递. 创建窗口实例函数: m_hWnd = CreateWin ...

  3. bzoj2441 小W的问题

    bzoj2441 按照纵坐标排序,从小到大插入数列中,每个点i维护一个data[i]表示未插入序列中横坐标小于i的数的个数(用线段树)其实点i就是“W”中第一个极小点,那么f[j]就等于1到j-1中所 ...

  4. 论文笔记--Fast RCNN

    很久之前试着写一篇深度学习的基础知识,无奈下笔之后发现这个话题确实太大,今天发一篇最近看的论文Fast RCNN.这篇文章是微软研究院的Ross Girshick大神的一篇作品,主要是对RCNN的一些 ...

  5. 跟我学Windows Azure 四 Cloud Service中的WebRole与WorkRole,及他们之间的通信

    Cloud Service 中WebRole就相当与我们的WebSite,而WorkRole相当与我们在服务器上写了个Windows Service,站在高可用的角度上来讲,Cloud Service ...

  6. 如何对web.config进行加密和解密

    http://blog.csdn.net/jf_jifei/article/details/6527390 在WEB网站开发过程中,如果我们将数据库连接字符串封装到.DLL文件中,将会给数据库和程序的 ...

  7. Java-instanceof关键字

    一.instanceof 在编写代码过程中,如果不知道一个对象属于哪一个类,这时instanceof关键字起到决定性作用,他会以boolean(true\false)反馈结果 class A{ pub ...

  8. redis缓存

    参考: java对redis的基本操作 http://www.cnblogs.com/edisonfeng/p/3571870.html 一.支持类型: key:一般设计为标准的字符串, values ...

  9. mysql:查询结果添加序列号

    select   (@i:=@i+1)   as   i,table_name.*   from   table_name,(select   @i:=0)   as   it

  10. JAVA多态的定义

    对于多态,可以总结它为: 一.使用父类类型的引用指向子类的对象: 二.该引用只能调用父类中定义的方法和变量: 三.如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法: ...