题目意思清晰明了:求两个数的商,不能使用乘法,除法或者求模运算等等。看似很简单的一道题,可是在排行榜上的正确率却是最低的一道,原因是情况很复杂,边界很难控制。需要考虑到的细节特别多,如:正负号,除数和被除数的取值,还有就是越界情况。其中越界情况最难考虑到,我也给拉低这道题的正确率增加了一份”功劳“,真的测试了好几遍才将条件考虑全面,我的代码中写有很多注释(大部分以测试用例形式给出)可以帮助大家分析特定情况,这类型的题目没有很强的技巧,唯一需要注意的就是”细心“。对了,还有一个问题就是如何不使用乘除法以及求模运算求商。我的思路是采用移位运算(其实是一种特殊的乘法)举个例子吧:
如 :23/4
(4<<3)= 32 > 23
(4<<2)=16 < 23
那么商在 2^2(4)~2^3(8)之间,最小为 4(第一部分)
23-4*2^2 = 23 - 16 = 7
4<<1 = 8 > 7 , 但是 4 < 7 所以可以求出第二部分的商为 1
综上所述,23/4 = 5(商为5)
如果还不理解那就参看我的代码吧,代码如下:
class Solution {
public:
int divide(int dividend, int divisor)
{
//求两个数的商
//1.被除数为0
if (divisor == 0)
{//不合法的数
return 0;
}
//2.除数为 0
if (dividend == 0)
{//除数为0
return 0;
}
//3.被除数为1
if (divisor == 1)
{
return dividend;
}
//4.被除数为2
else if (divisor == 2)
{
return dividend >> 1;
}
//5.考虑溢出问题,正数溢出或者负数溢出
double maxint = pow(2, 31) - 1;
if (dividend - maxint > 0.000001)
{
dividend = int(maxint);
}
if (divisor - maxint > 0.000001)
{
divisor = int(maxint);
}
if(dividend < maxint*(-1) && divisor < maxint*(-1))
{// 例如:-2147483648 / -2147483648
return 1;
}
if (dividend < maxint*(-1))
{
dividend = maxint*(-1);
}
if (divisor < maxint*(-1))
{//被除数越界 例如:(1~2147483647) / -2147483648
//divisor = maxint*(-1);
return 0;
}
//6.考虑正负号
int minus = 1; //商是否为负数
if (dividend < 0 && divisor < 0)
{
dividend *= -1;
divisor *= -1;
if (divisor > dividend)
{
return 0;
}
}
else
{
if (dividend < 0)
{
dividend *= -1;
minus = -1;
}
if (divisor < 0)
{
divisor *= -1;
minus = -1;
}
}
if (dividend == divisor)
{ //例如: 1 / -1
return 1*minus;
}
//7.被除数为1
if (divisor == 1)
{ //例如: -1 / -1
return dividend;
}
else if (divisor == 2)
{ //例如: -6 / -2
return dividend >> 1;
}
//8.开始求商 25 / 4 -> 6 4<<2--16 25 4<<3--32 所以,商在4~8之间
int left = 0;
int right = 1;
int ret = 0;
int mybeover = maxint / 2;
while (dividend > divisor)
{
left = 0;
right = 1;
while ((divisor << right) < dividend)
{
if ((divisor << left) >= mybeover)
{
break;
}
++left;
++right;
}
ret += 1 << left;
dividend -= divisor << left;
}
return ret*minus;
}
};
代码中注释挺多的,希望不会让大家看的瞌睡来了,我的代码可能有点啰嗦,不过主要还是分细节去讨论了可能出现的情况。