LeetCode/solutions/29. Divide Two Integers.md

61 lines
2.8 KiB
Markdown
Raw Normal View History

2018-12-24 15:14:53 +00:00
# [29. Divide Two Integers](https://leetcode.com/problems/divide-two-integers/)
# 思路
不使用取模、除法等操作求两数相除的商。
常规思路就是不断循环用被除数减去除数然后记录被减的次数即商,但是亲测会超时。
既然每次减去除数会超时那么一次性地减去除数的2倍、4倍、8倍......(之所以取2的次方倍是为了移位操作即可快速实现)呢,基于这个思路,我们有以下算法:
假设除数和被除数都是正数例如考虑15除3先用15-3发现结果等于12>3再尝试用15-6发现结果得9>3再尝试用15-12发现结果3=3再尝试用15减去24发现不够减
则应该用15-12然后余3此时商得4然后再考虑3除3依然用上面的思路得到商为1最终的结果就是将每一步得到的商相加即可。
如果是负数的话先取绝对值最后判断符号即可。
2020-06-17 12:38:49 +00:00
需要考虑唯一溢出的情况:
2018-12-24 15:14:53 +00:00
* `dividend == INT_MIN && divisor == -1`,结果是`-INT_MIN`超出了int的表示范围。
2020-06-17 12:38:49 +00:00
还需要考虑一些特殊情况:
* `dividend == 0`直接返回0即可
* `divisor == 1`,直接返回`dividend`因为我们是按照绝对值计算res的所以这样可以避免当`dividend=INT_MAX`中间结果溢出。
另外需要注意的是再用abs(x)求绝对值的时候要考虑x是否是INT_MIN。
1. 对于`divisor == INT_MIN`可以直接得到res为1或0直接返回即可
2. 而对于`dividend`,我们可以求`abs(dividend) - 1`来避免溢出最后加上这个1即可。
> 也可以先将x转换成long long型这样abs(x)返回的是long long型保证不溢出。
2018-12-24 15:14:53 +00:00
[参考](https://leetcode.com/problems/divide-two-integers/discuss/13407/Detailed-Explained-8ms-C%2B%2B-solution)
# C++
``` C++
class Solution {
public:
int divide(int dividend, int divisor) {
if(dividend == 0) return 0;
2020-06-17 12:38:49 +00:00
if(dividend == INT_MIN && divisor == -1) return INT_MAX; // 唯一可能的溢出情况
if(divisor == 1) return dividend;
if(divisor == INT_MIN) return dividend == INT_MIN ? 1 : 0;
2018-12-24 15:14:53 +00:00
2020-06-17 12:38:49 +00:00
int abs_dividend_minus_1 = abs(dividend + (dividend < 0 ? 1: -1));
int abs_divisor = abs(divisor), step = abs(divisor), step_i= 1;
int res = 0;
while(abs_dividend_minus_1 >= abs_divisor){
while(abs_dividend_minus_1 < step){
step >>= 1;
step_i >>= 1;
}
abs_dividend_minus_1 -= step;
res += step_i;
if(step <= (INT_MAX >> 1)){
step <<= 1;
step_i <<= 1;
}
2018-12-24 15:14:53 +00:00
}
2020-06-17 12:38:49 +00:00
if(abs_dividend_minus_1 + 1 == abs_divisor) res += 1;
if((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) return -res;
2018-12-24 15:14:53 +00:00
return res;
}
};
```