题目
- 链接 【剑指Offer II】 001 整数除法
- 描述
给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 '*'、除号 '/' 以及求余符号 '%' 。
注意: 整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1
总结一下
- 不使用 / * % 运算符
- 去掉小数
- 溢出数据的处理
- 输入与输出
输入:a = 15, b = 2 输出:7 解释:15/2 = truncate(7.5) = 7
思路
以 50 / 7 为例,先来枚举一下
被除数 | 除数 | 临时结果 |
---|---|---|
50 | 7 | 1 |
43 | 7 | 1 |
36 | 7 | 1 |
28 | 7 | 1 |
22 | 7 | 1 |
15 | 7 | 1 |
8 | 7 | 1 |
1 | 7 | 循环跳出 |
由此可以得到大概思路,具体思路见 代码注释 更详细 |
- 判断正负
- 零时结果相加
- 判断溢出数据
代码
class Solution {
public int divide(int a, int b) {
// 定义数据代替 a, b 否则溢出数据的正负无法准确判断
long num1 = a;
long num2 = b;
// 定义结果
long res = 0;
// 判断有无负数
boolean lessZero = false;
if (num1 < 0 && num2 > 0 || num1 > 0 && num2 < 0) lessZero = true;
// 将被除数与除数都先置为整数, 方便计算
if (num1 < 0) num1 = -num1;
if (num2 < 0) num2 = -num2;
// 进行计算
while (num1 >= num2) {
long tmp = num2;
long count = 1;
// 第一次 num2 = 7
// 第二次 num2 = 14
while (num1 >= tmp) {
tmp <<= 1;
count <<= 1;
}
// 类似于回溯 当 tmp <<= 1 也就是 tmp *= 2 后, 不进入循环, 那么这里需要 tmp /= 2
tmp >>= 1;
// 与 tmp /= 2 同理
count >>= 1;
// 减去已经 除了 的数字
num1 -= tmp;
// 每次都需要相加
res += count;
}
// 判断数据的正负性
res = lessZero ? -res : res;
// 处理溢出数据
if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) return Integer.MAX_VALUE;
// 返回结果
return (int)res;
}
}