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

  • 相关阅读:
    iphone6闪存检测
    knowledges address
    类linux系统/proc/sysrq-trigger文件功能作用
    iphone 6s pp助手 越狱
    C pointers
    ubuntu15.04 TLS
    ubuntu cenots 禁止本地登陆
    CentOS7
    CentOS7安全设置 yum-cron系统自动更新,firewalld防火墙简单使用
    SAS学习笔记之函数应用
  • 原文地址:https://www.cnblogs.com/alike/p/13218265.html
Copyright © 2011-2022 走看看