给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
输入: dividend = 10, divisor = 3
输出: 3
输入: dividend = 7, divisor = -3
输出: -2
该题第一个问题是特殊情况的处理,包括INT_MAX
和INT_MIN
的处理、负数转换成正数、判断商的正负情况。
另一个问题是如何进行除。已知左移和右移实际上相当于乘2和除2,所以利用左移或者右移来操作。另外主要根据(a+b)/c = a/c + b/c
。比如令a = c * 2^i
,则b
就是剩下的那部分,重新计算b
与c
的商。比如使用右移,右移被除数,直到被除数刚好大于除数,记录移动的次数i
,此时结果就可以根据移动次数和剩下的那部分来计算商。左移也可以,原理基本一致。
运行时间8ms,代码如下。
int myDivide(int dividend, int divisor) {
// printf("%d=%d\n", dividend, divisor);
int m = dividend;
int i = 0, result = 1;
if(dividend < divisor)
return 0;
while(dividend >= divisor) {
i++;
dividend = (dividend >> 1);
}
i--;
result = result << i;
return result + myDivide(m - (divisor << i), divisor);
}
int divide(int dividend, int divisor) {
int result = 0;
if(dividend == INT_MIN && divisor == INT_MIN)
return 1;
else if(dividend == INT_MIN) {
if(divisor > 0)
dividend += divisor;
else
dividend -= divisor;
result = 1;
}
else if(divisor == INT_MIN) {
return 0;
}
bool flag = true; //positive
if(divisor < 0) {
divisor = -divisor;
flag = !flag;
}
if(dividend < 0) {
dividend = -dividend;
flag = !flag;
}
if(dividend < divisor)
return flag ? result : -result;
int t = myDivide(dividend, divisor);
if(t == INT_MAX) {
return flag ? INT_MAX : INT_MIN;
}
result += t;
return flag ? result : -result;
}