zoukankan      html  css  js  c++  java
  • 29. Divide Two Integers

     
        /*
         * 29. Divide Two Integers
         * 2016-4-17 by Mingyang
         * 这个我们就得使用位运算。我们知道任何一个整数可以表示成以2的幂为底的一组基的线性组合,
         * 即num=a_0*2^0+a_1*2^1+a_2*2^2+...+a_n*2^n。
         * 基于以上这个公式以及左移一位相当于乘以2,我们先让除数左移直到大于被除数之前得到一个最大的基。
         * 然后接下来我们每次尝试减去这个基,如果可以则结果增加加2^k,然后基继续右移迭代,直到基为0为止。
         * 因为这个方法的迭代次数是按2的幂直到超过结果,
         * 所以时间复杂度为O(logn)
         * int的绝对值,int里面有一个特殊的数字:-2147483648,它的绝对值或者相反数 2147483648是超出int的范围的,
         * 对于这一情况需要特殊处理。所以不能直接调用 divide(-dividend, divisor)或者divide(dividend, – divisor)。
         * 也不能写 int dv = abs(dividend)。处理方式是使用long long来保存其绝对值
         * 计算绝对值的时候要写 long long dv = abs((long long)dividens)的原因是,
         * abs()有两个重载版本,其中一个是abs(int),另外一个是abs(long),如果不进行显式转换,
         * 则调用abs(int),对-2147483648的返回结果仍是-2147483648
         * 计算两个整数商的时候,有两种选择:将被除数dv右移或者将除数ds右移,循环终止条件是dv < ds。
         * 以上代码选用了右移被除数dv。原因是:当dv最高位(除符号位外)为1时,
         * 左移ds可能因为小于dv而将ds的有效位从最左移出,既会使比较出错,也可能导致死循环。
         * 最后,在return res这里,还是可能会出错的,但是就不在这段程序的考虑范围了,错误输入: -2147483648, -
         */
        public int divide(int dividend, int divisor) {
            //handle special cases
            if(divisor==0) return Integer.MAX_VALUE;
            if(divisor==-1 && dividend == Integer.MIN_VALUE)
                return Integer.MAX_VALUE; 
            //get positive values
            long pDividend = Math.abs((long)dividend);
            long pDivisor = Math.abs((long)divisor); 
            int result = 0;
            while(pDividend>=pDivisor){
                //calculate number of left shifts
                int numShift = 0;    
                while(pDividend>=(pDivisor<<numShift)){
                    numShift++;
                }     
                //dividend minus the largest shifted divisor
                result += 1<<(numShift-1);//这里用加,因为下面减去了曾经计算过的部分,所以用加
                //至于为什么要用1往左移?因为假设两个是倍数关系,96处于3的话,3左移5位到96,那么结果也是1左移5位
                pDividend -= (pDivisor<<(numShift-1));
            }     
            if((dividend>0 && divisor>0) || (dividend<0 && divisor<0)){
                return result;
            }else{
                return -result;
            }
        }
        /*
         *  这道题目也可以不用位运算
         *  见一下大神的算法
         *  每次减去那个数,然后减去以后除数乘以2,结果也乘以2.
         */
         public int divide1(int dividend, int divisor) {
                long  mul=1;long  count=0;
                Boolean neg=false;
                if(((dividend>0)&&(divisor<0))||((dividend<0)&&(divisor>0)))
                 neg=true;
                long a=Math.abs((long)dividend),b=Math.abs((long)divisor);
                long ori=b;
                while(a>=ori)
                {
                     a=a-b;
                     count+=mul;
                     b=b<<1;
                     mul=mul<<1;
                    if(a<b){
                        b=ori;
                        mul=1;
                    }
                }
                if(neg)
                 count*=-1;
                if(count>Integer.MAX_VALUE||count<Integer.MIN_VALUE)
                 return Integer.MAX_VALUE;
                else
                 return (int)count;
            }
  • 相关阅读:
    【数学】三分法
    【数学】【背包】【NOIP2018】P5020 货币系统
    【数学】【CF27E】 Number With The Given Amount Of Divisors
    【单调队列】【P3957】 跳房子
    【极值问题】【CF33C】 Wonderful Randomized Sum
    【DP】【CF31E】 TV Game
    【神仙题】【CF28D】 Don't fear, DravDe is kind
    【线段树】【CF19D】 Points
    【字符串】KMP字符串匹配
    【二维树状数组】【CF10D】 LCIS
  • 原文地址:https://www.cnblogs.com/zmyvszk/p/5403071.html
Copyright © 2011-2022 走看看