zoukankan      html  css  js  c++  java
  • [LeetCode]29 两数相除和一个小坑点

    给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
    
    返回被除数 dividend 除以除数 divisor 得到的商。
    
    示例 1:
    
    输入: dividend = 10, divisor = 3
    输出: 3
    示例 2:
    
    输入: dividend = 7, divisor = -3
    输出: -2
    说明:
    
    被除数和除数均为 32 位有符号整数。
    除数不为 0。
    假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231,  231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
    

      

    思路一:

    就是小学时候还没学除法的时候用的办法,用被减数去重复减去减数,但是毫无疑问这种办法效率并不高。如果其中一个Integer.MAX_VALUE

    另一个是1,就得循环那么多次,显然这不是做这个的好的解决办法。

    思路二:

    那么除了一个个将还有什么效率好的办法呢,我开始也想用移位,但是还是没能想出来,毕竟太菜。

    因为dividend即被减数规定了范围,那么能够被减数能整除的最大整数就是2的31次方,那么,从2的31依次开始试探,试探数之间的关系就是二倍关系。二倍关系就跟移位操作挂上够了,左移相当于X2,右移相当于/2,如果被除数/2^i(i=31,30...1,0)的商是大于除数的,则本题答案可以加上此时的2^i,同时,将被减数减去2^i,当然,在此之前,为了避免两个数异号而带来的不便,事先将两个数字做一下绝对值处理就好了。

    然后根据这条思路写出了如下代码:

    class Solution {
        public int divide(int dividend, int divisor) {
             boolean is = false;
            int res = 0;
            if(dividend==0)
                return 0;
            if(divisor==1)
                return dividend;
            if(dividend==Integer.MIN_VALUE&&divisor==-1)
                return Integer.MAX_VALUE;
            if((dividend<0&&divisor>0)||(dividend>0&&divisor<0))
                is = true;//如果异号
            long divd = Math.abs(dividend);
            long divs = Math.abs(divisor);
            for(int i = 31;i>=0;i--){
                if((divd>>i)>=divs){
                    res+=1<<i;
                    divd-=divs<<i;
                }
            }
            return is?-res:res;//异号结果变负
        }
    }
    View Code

    测几个用例,诶好像没问题。提交,WA(哭)

    输入:
    -2147483648
    2
    输出:
    0
    预期:
    -1073741824
    

      

    一时半会没想通,直到看见Math.abs()的源代码:

      /**
         * Returns the absolute value of an {@code int} value.
         * If the argument is not negative, the argument is returned.
         * If the argument is negative, the negation of the argument is returned.
         *
         * <p>Note that if the argument is equal to the value of
         * {@link Integer#MIN_VALUE}, the most negative representable
         * {@code int} value, the result is that same value, which is
         * negative.
         *
         * @param   a   the argument whose absolute value is to be determined
         * @return  the absolute value of the argument.
         */
        public static int abs(int a) {
            return (a < 0) ? -a : a;
        }
    

      

    如果是Integer.MIN_VALUE,不返回绝对值,返回本身。。所以这里算是一个小坑点了,做法就是,将int转化为long来去绝对值(因为本题规定了被除数范围,如果没有规定,强制转为long也可能没用。。)

    最后的AC代码:

    class Solution {
        public int divide(int dividend, int divisor) {
             boolean is = false;
            int res = 0;
            if(dividend==0)
                return 0;
            if(divisor==1)
                return dividend;
            if(dividend==Integer.MIN_VALUE&&divisor==-1)
                return Integer.MAX_VALUE;
            if((dividend<0&&divisor>0)||(dividend>0&&divisor<0))
                is = true;//如果异号
            long divd = Math.abs((long)(dividend));
            long divs = Math.abs((long)(divisor));
            for(int i = 31;i>=0;i--){
                if((divd>>i)>=divs){
                    res+=1<<i;
                    divd-=divs<<i;
                }
            }
            return is?-res:res;//异号结果变负
        }
    }
    View Code
  • 相关阅读:
    Java Spring AOP用法
    Spring IOC的简单实现
    随机数
    Java 正则表达式
    日期格式转换
    maven settings.xml详解
    JSP与Servlet的关系
    EL表达式学习
    FreeMarker学习2
    FreeMarker学习
  • 原文地址:https://www.cnblogs.com/Yintianhao/p/10909432.html
Copyright © 2011-2022 走看看