zoukankan      html  css  js  c++  java
  • 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)

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

    推到这里,大家应该懂了

    代码

     1 class Solution {
     2 public:
     3     static const int MAX_INT = 2147483647;
     4     static const int MIN_INT = -2147483648;
     5     
     6     int divide(int dividend, int divisor) {
     7         if(dividend == MIN_INT && divisor == -1)
     8         {
     9             return MAX_INT;
    10         }
    11         
    12         long pre = abs((long)dividend);
    13         long post = abs((long)divisor);
    14         int index;
    15         int rem = 0;
    16         
    17         while(pre >= post)
    18         {
    19             long tmp = post;
    20             for(index = 0; pre >= tmp; index ++, tmp <<= 1)
    21             {
    22                 pre -= tmp;
    23                 rem += (1 << index);
    24             }
    25         }
    26         
    27         return (dividend >> 31) ^ (divisor >> 31) ? -rem:rem;
    28     }
    29 };
    View Code
  • 相关阅读:
    年尾最有可能被老板“干掉”的十类人
    jQuery学习笔记
    HttpServletRequest的应用(一)
    getRequestDispatcher()与sendRedirect()的区别
    RequestDispatcher介绍
    原子类
    多线程基础
    asp.net Treeview节点保存成XML文件
    推荐小说给大家
    http://msdn.microsoft.com/zhcn/library/system.web.ui.webcontrols.gridview.rowediting.aspx
  • 原文地址:https://www.cnblogs.com/Shirlies/p/5655777.html
Copyright © 2011-2022 走看看