29. 两数相除
题目描述:给你两个整数,被除数
dividend
和除数divisor
。将两数相除,要求 不使用 乘法、除法和取余运算。整数除法应该向零截断,也就是截去(
truncate
)其小数部分。例如,8.345
将被截断为8
,-2.7335
将被截断至-2
。返回被除数
dividend
除以除数divisor
得到的 商 。注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是
[−231, 231 − 1]
。本题中,如果商 严格大于231 − 1
,则返回231 − 1
;如果商 严格小于-231
,则返回-231
。示例 1:
输入: dividend = 10, divisor = 3 输出: 3 解释: 10/3 = 3.33333.. ,向零截断后得到 3 。示例 2:
输入: dividend = 7, divisor = -3 输出: -2 解释: 7/-3 = -2.33333.. ,向零截断后得到 -2 。提示:
-231 <= dividend, divisor <= 231 - 1
divisor != 0
代码思路:
-
边界检查 :如果被除数(
dividend
)为0,直接返回0,因为0除以任何数都是0 -
特殊情况处理: 如果被除数是
Integer.MIN_VALUE
(-2^31),并且除数是-1,直接返回Integer.MAX_VALUE
,因为除以-1会导致溢出 -
确定结果的符号: 利用异或操作
^
,如果两个数的符号不同,结果为负 -
转换为长整型并取绝对值: 要处理可能超出整数范围的情况,将被除数和除数都转换为长整型,并取绝对值
-
进行除法操作: 使用一个循环从最高位开始,逐步检查被除数是否大于或等于除数的2的幂(2^n * 除数);如果是,那么将结果加上2的n次幂,并从被除数中减去2的n次幂乘以除数,这样循环直到检查完所有
这种方法的思路是通过逐步减去2的n次幂乘以除数来模拟除法过程,而不是使用传统的除法操作。
class Solution {public int divide(int dividend, int divisor) {if (dividend == 0) return 0;if (dividend == Integer.MIN_VALUE && divisor == -1) return Integer.MAX_VALUE;boolean flag = (dividend ^ divisor) < 0;long a = Math.abs(dividend);long b = Math.abs(divisor);int ans = 0;for (int i = 31; i >= 0; i--) {if ((a >> i) >= b) {ans += 1 << i;a -= b << i;}}if (flag) return -ans;else return ans;}
}
核心代码分析:
if ((a >> i) >= b) {ans += 1 << i;a -= b << i;
}
-
检查被除数是否足够大: ①
a >> i
:这是一个右移操作,它将被除数 a 向右移动i
位。是在检查 a 是否大于或等于b
的2的i
次幂,也就是2^i * b;②
(a >> i) >= b
:如果被除数a
右移i
位后仍大于或等于b
,说明2^i * b
是 a 的一个有效的部分 -
更新结果: ③
ans += 1 << i;
:如果2^i * b
是 a 的有效部分,将结果ans
增加2^i,
记录 a 中有多少个 b -
更新被除数: ④
a -= b << i;
:这是两步操作的结果,首先,b << i
计算出2^i * b
,然后这个值从 a 中减去,模拟实际的除法过程