LeetCode/solutions/29. Divide Two Integers.md

49 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [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最终的结果就是将每一步得到的商相加即可。
如果是负数的话先取绝对值最后判断符号即可。
另外需要考虑两个溢出的情况:
* `dividend == INT_MIN && divisor == -1`,结果是`-INT_MIN`超出了int的表示范围。
* ·dividend == INT_MIN && divisor == 1`,结果是`INT_MIN`虽然没有超过范围但是我们是按照绝对值计算结果的所以计算过程res也会溢出。
另外需要注意的是再用abs(x)求绝对值的时候一定要先将x转换成long long型这样abs(x)返回的才是long long型保证不溢出。否则若x=INT_MIN的话求绝对值就超过
int型表示范围了。
[参考](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;
if(dividend == INT_MIN && divisor == -1) return INT_MAX;
if(dividend == INT_MIN && divisor == 1) return INT_MIN;
int res = 0;
long long dvd = abs((long long)dividend); // 一定要先将dividend和divisor转换成long long型这样abs才返回long long型
long long dvs = abs((long long)divisor);
long long dvs_bk = dvs; // 除数备份
while(dvd >= dvs){
int curr = 1;
dvs <<= 1;
while(dvd - dvs >= 0){
curr *= 2;
dvs <<= 1;
} // dvd < dvs
dvs >>= 1;
dvd -= dvs;
dvs = dvs_bk;
res += curr;
}
if(dividend > 0 && divisor < 0) res *= -1;
else if(dividend < 0 && divisor > 0) res *= -1;
return res;
}
};
```