29. 两数相除

目录

一、问题描述

二、解题思路

三、代码

四、复杂度分析


一、问题描述

给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。

整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。

返回被除数 dividend 除以除数 divisor 得到的  。

注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−2^31,  2^31 − 1] 。本题中,如果商 严格大于 2^31 − 1 ,则返回 2^31 − 1 ;如果商 严格小于 -2^31 ,则返回 -2^31 。

二、解题思路

  1. 符号处理:首先要确定结果的符号。如果被除数和除数符号相同,则结果为正,否则为负。
  2. 除法通过减法实现:我们可以将除法转换为多次减法的过程,即被除数不断减去除数,直到剩余的部分小于除数为止。但为了提高效率,我们可以通过位移操作,每次将除数进行左移(即乘 2),直到超过被除数。
  3. 加速减法:为了避免每次减去除数都仅减去一个除数,我们通过不断左移除数,以找到一个接近被除数的最大数,然后进行减法,这样能快速逼近商值。
关键步骤:
  1. 处理符号:记录被除数和除数的符号,最后统一处理结果的符号。
  2. 避免溢出:当被除数是 INT_MIN(即 -2^31)且除数是 -1 时,结果会超过 32 位整数的最大值,因此需要提前返回 INT_MAX

三、代码

class Solution {
    public int divide(int dividend, int divisor) {
        // 特殊情况处理:防止溢出
        if (dividend == Integer.MIN_VALUE && divisor == -1) {
            return Integer.MAX_VALUE;
        }

        // 确定结果符号,结果为正或负
        boolean isNegative = (dividend < 0) ^ (divisor < 0);

        // 将被除数和除数转为负数处理,避免溢出(-2^31 转正会溢出)
        dividend = Math.abs(dividend);
        divisor = Math.abs(divisor);

        // 商的计算
        int result = 0;
        while (dividend - divisor >= 0) {
            int temp = divisor;
            int multiple = 1;
            // 将除数左移,直到它大于被除数
            while (dividend - (temp << 1) >= 0) {
                temp <<= 1;
                multiple <<= 1;
            }
            // 从被除数中减去移位后的最大除数
            dividend -= temp;
            // 累加商
            result += multiple;
        }

        // 返回带符号的结果
        return isNegative ? -result : result;
    }
}

四、复杂度分析

  • 时间复杂度:O(logN),其中 N 是被除数的绝对值。由于每次我们通过位移加速减法,减少的速度是指数级的,因此整体时间复杂度较低。
  • 空间复杂度:O(1),只用了常数级别的额外空间。
仿真ALU(算术逻辑单元)是一种计算机硬件组件,负责进行算术和逻辑运算。具体而言,仿真ALU可以实现以下48种功能: 1. 加法:将两个输入的二进制数相加,并输出结果。 2. 减法:将两个输入的二进制数相减,并输出结果。 3. 乘法:将两个输入的二进制数相乘,并输出结果。 4. 除法:将两个输入的二进制数相除,并输出结果。 5. 取模:将两个输入的二进制数取模,并输出结果。 6. 与逻辑:将两个输入的二进制数进行与逻辑运算,并输出结果。 7. 或逻辑:将两个输入的二进制数进行或逻辑运算,并输出结果。 8. 非逻辑:将输入的二进制数进行非逻辑运算,并输出结果。 9. 异或逻辑:将两个输入的二进制数进行异或逻辑运算,并输出结果。 10. 左移位:将输入的二进制数进行左移位操作,并输出结果。 11. 右移位:将输入的二进制数进行右移位操作,并输出结果。 12. 等于比较:判断两个输入的二进制数是否相等,并输出结果。 13. 不等于比较:判断两个输入的二进制数是否不相等,并输出结果。 14. 大于比较:判断第一个输入的二进制数是否大于第二个输入的二进制数,并输出结果。 15. 大于等于比较:判断第一个输入的二进制数是否大于等于第二个输入的二进制数,并输出结果。 16. 小于比较:判断第一个输入的二进制数是否小于第二个输入的二进制数,并输出结果。 17. 小于等于比较:判断第一个输入的二进制数是否小于等于第二个输入的二进制数,并输出结果。 18. 逻辑左移位:将输入的二进制数进行逻辑左移位操作,并输出结果。 19. 逻辑右移位:将输入的二进制数进行逻辑右移位操作,并输出结果。 20. 算术左移位:将输入的二进制数进行算术左移位操作,并输出结果。 21. 算术右移位:将输入的二进制数进行算术右移位操作,并输出结果。 22. 位与:将两个输入的二进制数进行位与操作,并输出结果。 23. 位或:将两个输入的二进制数进行位或操作,并输出结果。 24. 位非:将输入的二进制数进行位非操作,并输出结果。 25. 位异或:将两个输入的二进制数进行位异或操作,并输出结果。 26. 溢出检测:检测计算过程中是否发生溢出,并输出结果。 27. 位清零:将输入的二进制数指定位置为0,并输出结果。 28. 位设为1:将输入的二进制数指定位置为1,并输出结果。 29. 取反:将输入的二进制数按位取反,并输出结果。 30. 移位计数:统计输入的二进制数中1的个数,并输出结果。 31. 绝对值:计算输入的二进制数的绝对值,并输出结果。 32. 加1:将输入的二进制数加1,并输出结果。 33. 减1:将输入的二进制数减1,并输出结果。 34. 非零判定:判断输入的二进制数是否为非零,并输出结果。 35. 奇偶判定:判断输入的二进制数是否为奇数或偶数,并输出结果。 36. 正负判定:判断输入的二进制数是否为正数、零或负数,并输出结果。 37. 最大值判定:从输入的二进制数中判断最大值,并输出结果。 38. 最小值判定:从输入的二进制数中判断最小值,并输出结果。 39. 位取反:将输入的二进制数的指定位取反,并输出结果。 40. 位与非:将输入的两个二进制数进行位与非操作,并输出结果。 41. 位异或非:将输入的两个二进制数进行位异或非操作,并输出结果。 42. 加法与输入判断:判断两个输入的二进制数相加,是否符合输入的判断条件,并输出结果。 43. 减法与输入判断:判断两个输入的二进制数相减,是否符合输入的判断条件,并输出结果。 44. 乘法与输入判断:判断两个输入的二进制数相乘,是否符合输入的判断条件,并输出结果。 45. 除法与输入判断:判断两个输入的二进制数相除,是否符合输入的判断条件,并输出结果。 46. 输入选择:根据输入的选择信号,选择需要执行的操作,并输出结果。 47. 还原:将输入的二进制数还原为原始数据,并输出结果。 48. 自定义功能:根据需要,可以自定义额外的功能。 总之,仿真ALU可以灵活进行各种算术和逻辑运算,并输出结果,为计算机系统提供了多种功能和应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值