- Divide Two Integers
Divide two integers without using multiplication, division and mod operator.
If it will overflow(exceeding 32-bit signed integer representation range), return 2147483647
Example
Example 1:
Input: dividend = 0, divisor = 1
Output: 0
Example 2:
Input: dividend = 100, divisor = 9
Output: 11
代码如下:
这题的解法还是基于binary search。
- 每次shift<<1,直到dividend < (divisor<<shift)然后dividend -= (divisor << (shift - 1)); 如此往复,直到dividend < divisor;
- 一定要记得用long long。
如果不用long long,此题有无数陷阱:
a) isNegative也可以用 dividend * divisor < 0 来判断(不过此题不允许用乘法)。但乘积很可能超过INT_MAX或INT_MIN。如果用(long long) (dividend * divisor) < 0也不对,因为dividend * divisor本身就越界了。必须用 (long long)dividend * divisor
b) 如果dividend = -2147483648, divisor = -1,除下来等于2147483648 > 2147483647 已经越界。可以专门针对这种情况处理。
c) 如果dividend和divisor有负数,不能仅仅加个负号就将其变正。因为它们可能等于-2147483648,加负号又越界。
d) 在while ((divisor << shift) <= dividend) {
shift++;
}
这里当shift大到一定程度,divisor<<shift可能等于2147483648,这样又越界,实际还是负数(=-2147483648),所以还是小于dividend! 这个bug很难发现!
顺便说一下为什么2147483648实际上是存的-2147483648呢?
因为
2147483647 = 01111111 11111111 11111111 11111111
-2147483647表示为(2的补码)
10000000 00000000 00000000 00000001
-2147483648(2的补码)还可以比-2147483647少1,所以是
10000000 00000000 00000000 00000000
另外,实际上补码的补码就是原码(数的原始表示)
所以10000000 00000000 00000000 00000000 的补码是
11111111 11111111 11111111 11111111 + 1,第一个1是负号,所以
1111111 11111111 11111111 11111111 + 1 = 10000000 00000000 00000000 00000000=2147483648,这里第一个1是实际数字。加上负号,即-2147483648。
class Solution {
public:
/**
* @param dividend: the dividend
* @param divisor: the divisor
* @return: the result
*/
int divide(int dividend, int divisor) {
if (divisor == 0) return INT_MAX;
if (dividend == INT_MIN && divisor == -1) return INT_MAX; //important!
if (dividend == 0) return 0;
// bool isNegative = (((long long)dividend * divisor) > 0) ? false : true; //remember to use long long! Otherwise overflow (case: 2147483647 2)
bool isNegative = ((dividend < 0) && (divisor > 0)) || ((divisor < 0) && (dividend > 0));
long long dividendll = (long long)dividend, divisorll = (long long)divisor;
if (isNegative) {
if (dividendll < 0) dividendll = -dividendll; //note! it is incorrect for case dividend == -2147483648
else divisorll = -divisorll;
} else if (dividendll < 0) {
dividendll = -dividendll;
divisorll = -divisorll;
}
int quotient = 0;
while(dividendll >= divisorll) {
int shift = 1;
while ((divisorll << shift) <= dividendll) {
shift++;
}
quotient += 1 << (shift - 1);
dividendll -= (divisorll << (shift - 1));
}
return quotient * (isNegative ? -1 : 1);
}
};