LeetCode第29题-两数相除-java实现-图解思路与手撕代码
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2。
二分快速除法,通过每次将被除数的二倍与除数相比较从而快速确定商的一种算法,具体思路如下。
根据题目要求,首先排除边界条件,只需考虑除数为0和被除数为1、-1
除数 | 被除数 |
---|---|
0 | x |
x | 1 |
x or 最小值 | -1 |
为了后续计算方便,需要将两个数字转化为同号,而为了避免溢出,将被除数和除数转化为负数。
然后进行递归,每次将divisor的2倍与dividend相比较
若小于,则商quotient和divisor翻倍
若大于,则返回
div(dividend-上一次比较的被除数,divisor)+quotient
在递归操作的过程中,需要对可能发生的溢出进行判断,如果发生溢出,同样返回上式
若某次循环中dividend>divisor,则返回0。
代码如下(示例):
private static int divide(int dividend, int divisor) {
if (dividend == 0) {
return 0;
}
if (divisor == 1) {
return dividend;
}
if (divisor == -1) {
return dividend > Integer.MIN_VALUE ? -dividend : Integer.MAX_VALUE;
}
boolean isNegative = (dividend < 0 ^ divisor < 0);
dividend = dividend < 0 ? dividend : -dividend;
divisor = divisor < 0 ? divisor : -divisor;
int res = div(dividend, divisor);
return isNegative ? -res : res;
}
private static int div(int dividend, int divisor) {
if (dividend > divisor) {
return 0;
}
int temp = divisor, quotient = 1;
while (dividend < temp + temp && temp + temp < 0) {
temp = temp + temp;
quotient = quotient + quotient;
}
return quotient + div(dividend - temp, divisor);
}
二分快速除法源于二分法的思路,之前的边界条件判断和之后的溢出判断这两个细节操作比较重要。