• leetcode-29两数相除


    边界处理

    这题也是以前看过没理解,倒过来看理解的。

    • 首先越界可能只有一种,最小数除-1
    • 考虑简单情况,除数为1和-1以及被除数为0的情况,可以直接返回结果
    • 接下来考虑一般情况:先判断商的正负值,然后把两个数都转为负数,因为如果转为正数的话,INT_MIN会溢出。
    • 接下来就是不断翻倍,直到不满足条件,然后递归求解,具体如下(特别要注意除数相加可能的溢出问题):
    public int divide(int dividend, int divisor) {
            int sign=1;
            if(dividend>0&&divisor<0 || dividend<0&&divisor>0)
                sign=-1;
            int tmp=divisor;
            if(divisor==0)
                return 0;
            if(divisor==-1){
                if(dividend==Integer.MIN_VALUE)
                    return Integer.MAX_VALUE;
                return -dividend;
            }
            if(divisor==1)
                return dividend;
            dividend=dividend>0?0-dividend:dividend;
            divisor=divisor>0?0-divisor:divisor;
            int i=0;
    
            if(dividend<=divisor)
                i=1;
            else
                return 0;
            while(dividend<=divisor+divisor&&divisor+divisor<0){
                i=i+i;
                divisor=divisor+divisor;
            }
            if(sign==1)
                return i+divide(dividend-divisor, tmp);
            else
                return 0-(i+divide(dividend-divisor, tmp));
        }
    

    另一种容易理解的拆分代码:

    class Solution {
        public int div(int a,int b){//a,b都为负数
            int tmp=b;
            if(a>b)
                return 0;
            int cnt=1;
            while(a<=b+b&&b+b<0){//判断<0是因为防止负数相加溢出为正数
                cnt+=cnt;
                b+=b;
            }
            return cnt+div(a-b,tmp);
        }
        public int divide(int dividend, int divisor) {
            int sign=1;//判断是否异号
            if(dividend>0&&divisor<0 || dividend<0&&divisor>0)
                sign=-1;
            if(divisor==0)//特殊情况
                return 0;
            if(divisor==-1){//特殊情况
                if(dividend==Integer.MIN_VALUE)//唯一一种溢出情况,负最大除-1
                    return Integer.MAX_VALUE;
                return -dividend;
            }
            if(divisor==1)//特殊情况
                return dividend;
            dividend=dividend<0?dividend:0-dividend;//防止负最小转正最大时出错
            divisor=divisor<0?divisor:0-divisor;//统一转为负数
            return sign==1?div(dividend,divisor):0-div(dividend,divisor);
        }
    }
    

    几个自我收获:

    ++ 正数最大值加1会变成负最小,负数最小减1会变成正最大。这是补码计算得出的,也叫做溢出。
    ++ 这题如果有记录翻倍的过程应该会更快,减少了递归次数,用空间换时间。
    ++ 左移一位也就是当前数翻倍(右边补0),这题的话就是将除数进行移位,因为每个位置的数都翻倍,和也会翻倍,不过要考虑溢出问题

  • 相关阅读:
    《学习要像加勒比海盗》读书摘录
    【转载】关于软件测试的几点思考
    黑客与画家 摘录
    基于Jenkins的持续集成CI
    重新开始,整装出发
    java重写equals方法需要注意的几点
    《Google软件测试之道》摘录
    Using sql azure for Elmah
    Invalid object name ‘sys.configurations’. (Microsoft SQL Server, Error: 208)
    Cannot install ubuntu or other linux flavours on citrix Xen server
  • 原文地址:https://www.cnblogs.com/alike/p/13218265.html
Copyright © 2020-2023  润新知