【题目】
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
题目两句话,不用乘除模求两个数的除法。我把除法化成减法运算,结果直接TLE了。
后来看了下别人的做法,是把除数用左移来扩大,然后减去扩大之后的部分,重复下去,记录次数,就是 结果了。
代码如下:
class Solution {
public:
int divide(int dividend, int divisor) {
if(divisor == 0 || (dividend == INT_MIN && divisor == -1))
return INT_MAX;
bool native = (dividend < 0) ^ (divisor < 0) ? true : false;
long long dividend1 = labs(dividend);
long long divisor1 = labs(divisor);
int res = 0;
while(dividend1 >= divisor1){
long long tmp = divisor1, count = 1; //注意每次在此处初始化
while(dividend1 > (tmp << 1)){
tmp <<= 1;
count <<= 1;
}
dividend1 -= tmp;
res += count;
}
return native ? -res : res;
}
};
有几个点需要注意:
1.参数合法性检测。除数不为0自然都知道,但当除数为INT_MIN时,且被除数如果是-1的话,那么得到的结果是INT_MAX+1,会产生溢出。
2.使用long long类型来处理溢出。我们计算时需要对被除数和除数的绝对值进行计算这是自然的,如果除数或者被除数为INT_MIN,取绝对值是会产生溢出的,所以直接采用long long类型计算,并且下面的tmp和count也采用long long类型,都是为了避免溢出。
3.算法核心,举个例子吧:15 ÷ 3
首先我们要提高效率,就要扩大被除数,让我们减法的过程尽可能少。那么就采用左移<<,如果左移结果不大于15就继续左移,此例中我们可以得到左移的序列为:3->6->12,但是左移产生的包含除数3的次数也是移位级别增长的,所以count同时也要左移。并累加结果到res。
此例情况比较特殊,如果出现最后一次左移的结果为x,15-x>3的话,我们需要重新开始左移,count归1,tmp归divisor,重新开始计数,再次累加到res。
如此循环万福,不满足条件跳出循环,即得到正确的结果。