题目

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. linux操作

    进入root权限:sudo su 把文件b的拥有者改成a:chown a b 如果保存文件的时候出现"无法创建备份文件",是因为这个文件所在的文件夹不属于当前用户,需要把这个文件所 ...

  2. 兼容ie7、8、9、10、FF、Chrome的遮罩显示

    经常碰到这种情形,要实现图片上有一层遮罩和按钮,鼠标滑过时遮罩颜色变深且按钮图片变化,磕磕碰碰终于弄出来题目所述兼容的解决方案. 对于遮罩的实现,将遮罩层.按钮.图片放置在同一个div中,根据abso ...

  3. Android 图片上传

    上传方式:两种   1:Base64() (1):获取图片路径,将图片转为String 类型 (2):通过post提交的方式.以键值对的方式上传到服务器,和一般的提交关键字没有任何区别. (3):这种 ...

  4. Majority Element II

    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorit ...

  5. phpMyAdmin如何设置float小数点

    在长度/值设置 5,2就行了哈

  6. Java实现多线程的三种方式

    Java多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.前两种方式启动的线程没有返回值 ...

  7. android 开发学习笔记 (一)

    每个app 都有一个自己的 linux 进程: 每个进程都在自己的虚拟机里执行 两个app 可以跑在一个进程,一个vm里 android app 四大组件:activity,content provi ...

  8. 让CSS布局更加直观:box-sizing

    让CSS布局更加直观:box-sizing 如果你写过CSS或者你接触过CSS,相信你一定对盒子模型一点都不陌生.CSS其中一个让人比较困惑的地方就在于它的盒子模型中关于高度和宽度的计算,别说那些初学 ...

  9. MaskEdit 使用方法

    它有一个  MaskEdit 属性(注意,属性) 打开后有一个   Input Mask 编辑框 格式符意义 L 允许输入英文字母,且一定要输入                      l 允许输入 ...

  10. android studio 各种问题

    1.dexDebug ExecException finished with non-zero exit value 2 全bug日志如下: (Error:Execution failed for t ...