0029_Divide Two Integers

本文介绍一种不使用乘除和模运算实现整数除法的Java算法。利用位操作实现高效运算,通过2的幂次组合原理求解商,避免了传统运算符的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Divide two integers without using multiplication, division and mod operator.

If it is overflow, return MAX_INT.

JAVA

方法一

控制好符号及边界条件,直接考虑循环使用被除数减去除数,统计循环次数即为结果,果然超时。

方法二

由于不能直接进行乘除和取余操作,所以直接考虑使用位操作符来运算,但是虽然知道位操作带来的乘除关系,但是不知道如何计算除法,只好看看其他人怎么做的。参考http://blog.youkuaiyun.com/linhuanmars/article/details/20024907,作者给出了一个忘了很多年的公式:一个整数可以表示成以2的幂为底的一组基的线性组合,即

num=a020+a121+a222+...+an2n

所以可以将 an 理解为除数的倍数,即 an=kndivisor2n ,而 ni=1(ki2i 即为商。以51÷5为例:
51=1520+1521+0522+1523=15+25+85
所以51÷5的商是10,其中2^0不算。这种方法的效率在前20%,可见数学是多么的有用~~~

public class Solution {
    public int divide(int dividend, int divisor) {
        if(divisor == 0){
            return Integer.MAX_VALUE;
        }
        if(dividend == 0 ){
            return 0;
        }
        if (dividend == divisor){
            return  1;
        }
        //开始讲这个判断与dividend = 0 放在了一起,使用或的关系,后来发现这是不对的,因为当dividend = Integer.MIN_VALUE时结果应该是1.也是就是说要记着int型负数的绝对值会比正数大,所以一旦dividend != divisor而divisor == Integer.MIN_VALUE,则必有Math.abs(dividend) < Math.abs(divisor),此时商一定是0.
        if(divisor == Integer.MIN_VALUE){
            return 0;
        }
        int result = 0;
        //这里的经验值得记一下,当被除数取反可能会导致溢出时,可以先将这个数做一次运算
        if(dividend == Integer.MIN_VALUE){
            if(divisor == -1){
                return Integer.MAX_VALUE;
            }
            dividend += Math.abs(divisor);
            ++result;
        }
        if(divisor == -1){
            return -dividend;
        }
        boolean negative = false;
        if((dividend > 0 && divisor < 0) ||
                (dividend < 0 && divisor > 0)){
            negative = true;
        }
        dividend = Math.abs(dividend);
        divisor = Math.abs(divisor);
        int count = 1;
        //刚开始写的时候用的是while(divisor <= dividend),后来发现当divisor移位运算后有可能溢出,导致死循环,于是改成了while(divisor << 1 <= dividend),心想dividend一定不会越界,只要比他小就没问题,但是发现当dividend很大时,divisor最后一次移位时可能直接越界变成负数,导致死循环,于是改成了现在这样。
        while((divisor << 1 > 0) && (divisor << 1 <= dividend)){
            divisor <<= 1;
            count <<= 1;
        }
        while (count > 0){
            if (divisor <= dividend){
                dividend -= divisor;
                result += count;
            }else {
                divisor >>= 1;
                count >>= 1;
            }
        }
        if(negative){
            result = -result;
        }
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值