leetcode-【中等题】Divide Two Integers
题目
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的更多相关文章
- 乘风破浪:LeetCode真题_029_Divide Two Integers
乘风破浪:LeetCode真题_029_Divide Two Integers 一.前言 两个整数相除,不能使用乘法除法和取余运算.那么就只能想想移位运算和加减法运算了. 二.Divide T ...
- leetcode面试准备:Divide Two Integers
leetcode面试准备:Divide Two Integers 1 题目 Divide two integers without using multiplication, division and ...
- leetcode第28题--Divide Two Integers
Divide two integers without using multiplication, division and mod operator. 分析:题目意思很容易理解,就是不用乘除法和模运 ...
- 【一天一道LeetCode】#29. Divide Two Integers
一天一道LeetCode系列 (一)题目 Divide two integers without using multiplication, division and mod operator. If ...
- [Leetcode][Python]29: Divide Two Integers
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 29: Divide Two Integershttps://oj.leetc ...
- LeetCode OJ:Divide Two Integers(两数相除)
Divide two integers without using multiplication, division and mod operator. If it is overflow, retu ...
- 【LeetCode】029. Divide Two Integers
Divide two integers without using multiplication, division and mod operator. If it is overflow, retu ...
- 【LeetCode】29. Divide Two Integers
题意:不用乘除求余运算,计算除法,溢出返回INT_MAX. 首先考虑边界条件,什么条件下会产生溢出?只有一种情况,即返回值为INT_MAX+1的时候. 不用乘除求余怎么做? 一.利用减法. 耗时太长, ...
- leetcode 中等题(2)
50. Pow(x, n) (中等) double myPow(double x, int n) { ; unsigned long long p; ) { p = -n; x = / x; } el ...
- leetcode 中等题(1)
2. Add Two Numbers(中等) /** * Definition for singly-linked list. * struct ListNode { * int val; * Lis ...
随机推荐
- 当窗体获得焦点时禁用max快捷键
最近一段时间一直在MXS里用dotnet写界面...写的各种头晕眼花... 过程中遇到了 TextBox 控件输入时 与max快捷键冲突的问题. 解决办法是 用 MaxTextBox 控件替换,今天请 ...
- Android AsyncTask 简单用法
简介 AsyncTask 是一个轻量级的异步处理类.使用是需继承自该类.可以方便的执行异步任务并且在将进度显示在UI上. 注意事项 AsyncTask只适合处理轻量级的任务即耗时几秒或者几十秒的任务. ...
- SQL 用户定义表类型,在存储过程里使用表类型,表参数作参数
.定义表类型SUTDENTTYPE,包含三个字段,分别对应学生表的NAME,SEX和PHONE.之所以如此创建,我是准备在插入新学生数据的存储过程中,以它为参数. GO CREATE TYPE S ...
- 模拟discuz发帖的类实现
一直想弄个discuz的数据采集程序,这2天研究了下discuz发帖涉及的几个数据库表,这里分享一下自己的处理方法. discuz发表主题设计的几个表:(这里列出了主要的几个相关的表) 1.主题表 p ...
- winform 异步添加文本提示
后台代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data ...
- 在CentOS中将/var等已有目录挂载到新添加的硬盘
1.查看当前硬盘使用状况: [root@gluster_node1 ~]# df -h Filesystem Size Used Avail Use% Mounted on / ...
- [PHP] - Laravel 5 的 Hello Wold
吐槽一段 整了半天,Laravel下载麻烦得可以去死.先要安装composer,而composer又被共墙了,之后又要安装git,安装完git还要注册git,等等.... 最终放弃这种玩法,太恶心了. ...
- WeX5 - AJAX跨域调用相关知识-CORS和JSONP
http://docs.wex5.com/ajax-cross-domain/ 1.什么是跨域 跨域问题产生的原因,是由于浏览器的安全机制,JS只能访问与所在页面同一个域(相同协议.域名.端口)的内容 ...
- python---set集合
集合(set)是一个无序不重复元素的序列. #!/usr/bin/python3 student = ({'Tom', 'Jim', 'Mary', 'Tom', 'Jack', 'Rose'}) p ...
- linux新增用户并增加sudo权限
创建用户.设置密码: useradd testuser 创建用户testuserpasswd testuser 给已创建的用户testuser设置密码 增加sudo权限: #vi /etc/sudoe ...