题目:

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

If it is overflow, return MAX_INT.

代码:

class Solution {
public:int divide(int dividend, int divisor) {if (divisor==0) return dividend>=0 ? INT_MAX : INT_MIN;if (divisor==-1 && dividend==INT_MIN) return INT_MAX;// record negative or positiveint sign = 1;sign = dividend<0 ? -sign : sign;sign = divisor<0 ? -sign : sign;// transfer to non negative long long type & get rid of overflowunsigned long long _dividend = abs((long long)dividend);unsigned long long _divisor = abs((long long)divisor);if ( _dividend < _divisor ) return 0;// using bit manipulation to simulate binary multiplyunsigned long step = 1;while ( _dividend > _divisor ){_divisor = _divisor << 1;step = step << 1;}// cout << "step:" << step << endl;// cout << "_divisor:" << _divisor << endl;unsigned long res = 0;while ( _dividend >= abs((long long)divisor) ){while ( _dividend >= _divisor){_dividend -= _divisor;res = res + step;}_divisor = _divisor >> 1;step = step >> 1;}return sign==1 ? res : -res;}
};

tips:

这道题非常好,即考查了bit manipulation又考查了类型转换的细节。

做题的过程中,学习了下面这个blog的优秀思路(http://yucoding.blogspot.sg/2013/01/leetcode-question-28-divide-two-integers.html)

1. 不让用乘法、除法、幂运算等。但还是要做除法,这个时候可以用bit manipulation。本质就是用二进制运算代替十进制运算。

  比如 155/3 ,如果不让你用除法,只允许用乘法或加法,该怎么做呢?

  做法1(加法):

      3+3+...+3+3==153,result=51

      这种解法最直观,但也最耗时,时间复杂度为O(n)

  做法2(乘法+加法):

      1)3*100=300>155 , 得知result<100,10个3*10大于被除数

      2)3*10=30<155, 得知result>10 1个3*10小于被除数

         155-30-30-30-30-30==5<30, result = result +50

      3) 3*1=3<5,得知result大于一个3*1小于10个3*1

        5-3=2<3,result = result +1 = 51

      最终得到的结果是 155 = 3*5*10^1 + 3*1*10^0 + 2。

      解释如下,如果用10的幂构成的多项式(多项式每个项目前面有固定的系数就是被除数);

      并在每一项前面配上一个变化系数(加颜色),155就被表示上述的形式

显然做法2的时间复杂度log(n)更低,按照题意的要求,乘以10这种做法肯定是不行了,所以把10换成2,改用移位运算,右移一次等于乘以2。

比如 15/3 = 3*2^2 + 3*2^0 , 可得商为2^2+2^0=5。

2. 这道题还有一个细节就是变量类型转换,以及涉及到边界的临界问题:

a) INT_MIN=-2147483648

但abs(INT_MIN) 呢?还是-2147483648。因为int的上限就是2147483647;因此如果除数被除数有一个是INT_MIN都没法变成正的啊!

如果是 unsigned long long v = abs(INT_MIN)呢?这种的可以么?结果是:18446744071562067968,还是不对。

好奇这个数咋来的呢?

复习了知识点:负数在计算机中以补码形式表示。

INT_MIN的补码形式是1000....000(31个0);

现在要把INT_MIN转成unsigned long long类型的,这中间发生了什么呢?

1) 把有符号转无符号数,如果是负数的话,要取补码

2) unsigned long long是64位的,INT_MIN是32位的;转换后高位要补上0

这就涉及到顺序的问题:先取补码还是先高位补0?

根据事实结果:先补高位的0,再取补码

补高位0:0...0(32个零)10...000(31个零)

取补码:a)先取反码 1...1(32个1)01...1(31个1)

    b)再对反码加1 1...1(32个1)10...0(31个0)

这样操作之后,结果就是2^64-2^31,恰好等于18446744071562067968,就对上了。

但是这个并不是我们需要的,我们要得到的是2147483648,怎么办呢?

unsigned long long v = abs((long long)INT_MIN) 这样的结果是2147483648。

这个过程是怎样的呢?

1)先在高位补上32个0,变成了0...0(32个零)10...0(31个零)

2)abs函数识别最高位为0,直接不变

这样v的取值就是2^31=2147483648,对上了。

补几个参考资料blog:

http://www.cnblogs.com/lknlfy/archive/2013/04/02/2996320.html

============================================

第二次过这道题,按照第一次的思路coding,改了几个corner case,最后AC了,代码比第一次要简洁清晰很多。

class Solution {
public:int divide(int dividend, int divisor) {// corner casesif ( divisor==0 ) return dividend>=0 ? INT_MAX : INT_MIN;if ( dividend==0 ) return 0;if ( dividend==INT_MIN && divisor==-1 ) return INT_MAX;int sign = 1;sign = divisor>=0 ? sign : -sign;sign = dividend>=0 ? sign : -sign;unsigned long long n = abs((long long)dividend);unsigned long long d = abs((long long)divisor);if ( n<d ) return 0;if ( n==d ) return sign;// bit manipulation simluate decimalunsigned long long ret = 0;unsigned long long base = 1;while ( base*d<n ) base = base<<1;while ( base>=1 ){if ( base*d<=n ){ret += base;n = n - base*d;}base = base >> 1;}return ret*sign;}
};

转载于:https://www.cnblogs.com/xbf9xbf/p/4563659.html

【Divided Two】cpp相关推荐

  1. 【学习点滴】cpp遇到的一些疑问和积累

    目录 1.虚函数的问题 2.多种构造函数问题 3.全局变量和局部变量重名的问题: 4.有符号数溢出问题 5.自己实现c的字符串库函数 6.栈破坏问题 7.右值引用 移动构造和移动赋值 8.字符串作为h ...

  2. 【Sort List】cpp

    题目: Sort a linked list in O(n log n) time using constant space complexity. 代码: /*** Definition for s ...

  3. Hdu 1072 【广搜】.cpp

    题意: 给出一个n*m的矩阵, 0 表示不可走 1 表示可走 2 表示起点 3 表示终点 4 表示可走且走到这一步可以满血 某人一开始有6滴血,走一步少一滴..到0就死了.. 可以走到4的位置满血再走 ...

  4. POJ 1904 【强连通分量】.cpp

    题意: 很久很久以前.. 有一个国王.. 他有好几个儿子.. 这些王子都喜欢上了邻国的公主.. 他们准备迎娶自己喜欢的公主中的一个.. 国王就让宰相给列一个清单.. 宰相就给了国王一个清单..上面写明 ...

  5. 【Next Permutation】cpp

    题目: Implement next permutation, which rearranges numbers into the lexicographically next greater per ...

  6. POJ 3422 【最大费用】.cpp

    题意: 给出一个每一格带值的矩阵 每一次只可以从左上角走到右下角 问走过k次后最多能得到多少值 P.S 走过的格子值会变成0 输入: 给出一个n 和 k 给出n*n 矩阵 思路: 因为求的是最大值 所 ...

  7. 题解洛谷P4752 【Divided Prime】

    此题的感想:我个人感觉这道题绿的有点假..不过实际上是大佬们的程序我没看懂.这里想给大家普及一个新的思路. 算法: ①:我们知道,如果一个数的非1因数个数减去第二个数的非一因数个数>1的话,那么 ...

  8. 【Visual C++】游戏开发笔记十五 游戏人工智能(一) 运动型游戏AI .

    本系列文章由zhmxy555编写,转载请注明出处.  http://blog.csdn.net/zhmxy555/article/details/7434317 作者:毛星云    邮箱: happy ...

  9. 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | Class.cpp#findClassNoInit 函数 | DexFile.cpp#dexFindClass 函数分析 )

    文章目录 前言 一.Class.cpp#dvmDefineClass 函数分析 二.Class.cpp#findClassNoInit 函数分析 三.DexFile.cpp#dexFindClass ...

最新文章

  1. 如何让你的Nginx 提升10倍性能?
  2. oracle vm virtualbox如何设置u盘启动_电脑自主U盘装机 如何设置U盘启动
  3. python对接微信支付_python3接入微信企业支付实现小程序提现
  4. 红帽技术开放日:参与开源社区不只有贡献代码这一种方式
  5. MVC 下 JsonResult 的使用方法(JsonRequestBehavior.AllowGet)转
  6. android布局之LinearLayout 转
  7. [实战]HM-Router configuration for TP ROOM
  8. Android 开发 Tips
  9. 关抢占 自旋锁_关于Redis分布式锁这一篇应该是讲的最好的了,先收藏起来再看!...
  10. 今天发现新大陆:haml和Emmet
  11. 用计算机的知识服务社会,科研育人案例-董立红
  12. 浙大python读者验证码_Python实现简单生成验证码功能【基于random模块】
  13. C语言判断文件编码格式
  14. 我的家乡河北涿州岐沟村(岐沟关)
  15. jsp物流配送管理系统
  16. NDS –无法加载数据(解决方案)–如何更新R4内核
  17. 方寸间见万物灵机:我们在世界人工智能大会听到了哪些华为AI故事?
  18. 杨辉三角数学性质及参考例题
  19. 关于函数YEAR、NOW的使用方法以及求年龄的函数公式
  20. java计算机毕业设计民宿运营管理网站源码+mysql数据库+系统+lw文档+部署

热门文章

  1. JavaScript-在当前显示区范围内实现点不到的小方块
  2. HTML5 -- WebSocket
  3. 『51cto十周年庆典』社区活动大汇总
  4. [转][C#] .net动态编译C# 和 VB
  5. CGAffineTransform 放射变换
  6. 兼职做了DB设计和维护的体会(存储过程,视图,函数,范式)
  7. spring-security3 配置和使用
  8. LogDashboard 1.0.4 版本发布
  9. generator异步
  10. react 项目实战(二)创建 用户添加 页面 及 fetch请求 json-server db.json -w -p 8000...