力扣LeetCode第29题:两数相除,beat100%解法

思路

官方题解中有快速乘,那当然也就有快速除。思路就是模拟手动计算除法,二进制的除法和十进制也非常类似

解题过程

(1)首先要把除数和被除数“对齐” (2)然后除数和被除数进行比较,如果小于被除数则这一位商0,否则商1 (3)把每一位的01组装起来就是最终的结果 里面的一些边界问题还需要注意处理一下。

复杂度

时间复杂度: O(logN),其中N为被除数和除数倍数差,也即商。logN即为被除数和除数二进制的位数差,比如1011111/11,那么logN为7−2=5

空间复杂度: O(1)

class Solution {
    public int divide(int dividend, int divisor) {
        //如果除数是最小的int
        if(divisor == Integer.MIN_VALUE){
            return dividend == divisor?1:0;
        }

        //注意最小的int为-2^31,最大的int为2^31-1,如果商为2^31,越界,应返回2^31-1
        if(dividend == Integer.MIN_VALUE){
            if(divisor == 1){
                return dividend;
            }
            if(divisor == -1){
                return Integer.MAX_VALUE;
            }
        }

        //为了便于统一进行移位等操作,都转成正数来处理
        //如果dividend == Integer.MIN_VALUE,为了避免边界问题,先加上一个除数的绝对值,保证不越界
        //如果加上了绝对值,后面商的绝对值需要+1,所以设置一个标志位
        boolean plusOne = false;
        if(dividend == Integer.MIN_VALUE){
            dividend = dividend + (divisor>0?divisor:-divisor);
            plusOne = true;
        }


        //都转为正数处理
        boolean changeSymbol = false;
        if(divisor < 0){
            divisor = -divisor;
            changeSymbol = !changeSymbol;
        }

        if(dividend < 0){
            dividend = -dividend;
            changeSymbol = !changeSymbol;
        }

        //不断把除数进行左移,直到和被除数对齐
        int move = 0;
        int constant = (1<<30);
        while(divisor < dividend){
            //如果符号位后紧接的一位,也就数字位的最高位已经为1了,则不应该再左移了
            if( (divisor & constant) > 0){
                break;
            }
            divisor <<= 1;
            move++;
        }

        // int move = Integer.numberOfLeadingZeros(divisor) - Integer.numberOfLeadingZeros(dividend);
        // divisor <<= move;

        
        //模拟手算除法的过程,无非是二进制而已。十进制每一位可以商0-9,二进制中只能商0或1
        int ans = 0;
        for(int i = move;i>=0;i--){
            if(dividend < divisor){
                divisor >>= 1;
            }else{
                ans += (1 << i);
                dividend -= divisor;
                divisor >>= 1;
            }
        }

        ans = plusOne?ans+1:ans;
        return changeSymbol?-ans:ans;
    }
}
  • 11
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值