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),这题的话就是将除数进行移位,因为每个位置的数都翻倍,和也会翻倍,不过要考虑溢出问题

posted @ 2020-07-01 11:29  浮尘2333  阅读(118)  评论(0编辑  收藏  举报