前言
力扣第二十九题 两数相除
如下所示:
给定两个整数,被除数 dividend
和除数 divisor
。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend
除以除数 divisor
得到的商。
整数除法的结果应当截去(truncate)
其小数部分,例如:truncate(8.345) = 8
以及 truncate(-2.7335) = -2
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333…) = truncate(3) = 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333…) = -2
一、思路
如果不用乘法怎么知道除法的结果呢?其实也很简单就是 累加
。举个例子,要知道 9 / 4
等结果,就一直将4相加, 4 + 4 = 8 < 9
且 4 + 4 + 4 = 12 > 9
,故 9/4 = 2
但是这样一直累加会有一个问题,就是次数会很多。比如要计算 100 / 2
要一直累加 50 次才能得到正确的结果。为了合理的减少累加的次数,这里可以使用 倍增法,就是下一次相加的结果乘以二。如果和比被除数大,则变小一点。
举个例子
此处以 100/2
作为例子,具体的步骤如下所示:
ret表示返回结果,ret = 0
- 第一步:
2 < 100
,ret = 1 - 第二步:
2 + 4
< 100, ret = 1 + 2 = 3 - 第三步:
(2 + 4) + 8 < 100
, ret = 3 + 4 = 7 - 第四步:
(2 + 4 + 8) + 16 < 100
,ret = 7 + 8 = 15 - 第五步:
(2 + 4 + 8 + 16) + 32 < 100
,ret = 15 + 16 = 31 - 第六步:
(2 + 4 + 8 + 16 + 32) + 64 > 100
,ret = 31。此时出现了大于的情况,下一次累加的数要缩小到加上后不会出现大于的情况 - 第七步:此时会一直试着寻找合适的累加数,直到寻找到累加数 32 为合适的值
(2 + 4 + 8 + 16 + 32) + 32 < 100
,ret = 31 + 16 = 47 - 第八步:再次加上 32 会发生大于的情况,所以会再次寻找合适的累加数 4 ,即
(2 + 4 + 8 + 16 + 32 + 32) + 4 < 100
,ret = 47 + 2 = 49 - 第九步:再次加上 4 会发生大于的情况,所以会再次寻找合适的累加数 2,
(2 + 4 + 8 + 16 + 32 + 32 + 4) + 2 = 100
,ret = 49 + 1 = 50 - 最后,返回结果
ret = 50
在实际实现的过程中因为会将比较的值转为 long 类型,便于处理。
二、实现
实现代码
为了方便处理,我们先判断出最终结果的正负值。然后再将被除数和除数转为正数,便于后续处理。
/**
* 倍增法
*/
public int divide(int dividend, int divisor) {
// 特殊情况
if(dividend == 0) return 0;
if(divisor == 1) return dividend;
if(divisor == -1){
if(dividend> Integer.MIN_VALUE) return -dividend;
return Integer.MAX_VALUE;
}
// 结果
int ret = 0;
// 转为long
long d = dividend;
long r = divisor;
// 判断正负号
boolean flag = true;
if (d > 0 && r < 0 || d < 0 && r > 0) {
flag = false;
}
// 保证是两个正数
d = d < 0 ? -d : d;
r = r < 0 ? -r : r;
// 开始倍增
long temp = 0;
long add = r; // 累加值
int multiple = 1; // 倍数
while (temp < d || add > r) {
if (temp == d) {
break;
}
// 选择合适的累加数
while (temp + add > d) {
add = add >> 1;
multiple = multiple >> 1;
}
ret += multiple;
temp += add;
add += add;
multiple += multiple;
}
// 返回结果
return flag ? ret : -ret;
}
测试代码
public static void main(String[] args) {
int ret = new Number29().divide(100 , 2);
System.out.println(ret);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥