题目来源:https://leetcode-cn.com/problems/divide-two-integers/
大致题意:
给定两个 int 范围内的整数,求出它们的商,只保留整数部分即可
思路
我自己只想到了循环减代替除的方法,这个明显时间复杂度高,而且边界溢出情况也没搞对,实在惭愧。
看题解,一个哥们使用了循环减的优化(我随便起的名字)。
循环减的优化
正常的循环减:
- 使用被除数减去除数,同时商值加 1(初始为 0),重复这个操作直至被除数小于除数为止
优化的循环减:
- 判断被除数是否大于当前的除数,若大于,则除数翻倍,商值翻倍(初始为 1),重复这个操作直至被除数小于除数。然后将被除数减去除数最后一次翻倍前的数,对得到的差重复这个操作,并将得到的商累计入当前商。很明显,这是一个递归
同时要注意正负号问题,以及边界问题
- 正负号问题,提前根据两个操作数的正负做标记
- 边界问题,考虑溢出问题。即 32位整数的最小值 -2^31 除以 -1 时,会得到 2^31,造成溢出,需要特判
代码:
public int divide(int dividend, int divisor) {
if (divisor == -1) {
// 特判溢出的情况,取答案为最大值
if (dividend == Integer.MIN_VALUE)
return Integer.MAX_VALUE;
}
// 标记正负
int sign = 1;
long dividengLong = (long) dividend;
long divisorLong = (long) divisor;
if (dividend < 0) {
sign = -sign;
dividengLong = -dividengLong;
}
if (divisor < 0) {
sign = -sign;
divisorLong = -divisorLong;
}
// 优化的循环减
int ans = div(dividengLong, divisorLong);
// 给结果加上正负
return sign > 0 ? ans : -ans;
}
public int div(long a, long b) {
if (a < b) {
return 0;
}
// 商
int count = 1;
// 待迭代的除数
long mul_b = b;
// 若被除数大于除数的翻倍,则将除数和商翻倍
while ((mul_b + mul_b) <= a) {
count = count + count;
mul_b = mul_b + mul_b;
}
// 累计当前的商和余数的商
return count + div(a - mul_b, b);
}
445

被折叠的 条评论
为什么被折叠?



