题目
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
思路一:报超时错误
/*
完成两个数的除法,不能用乘法、除法、和求余运算
思路:由于有上面的限制,因此只能用加法和减法来做此题
*/
//函数中第一个参数为:被除数,第二个参数为:除数。
//例如:如24÷8=3,中24就为被除数,8为除数
/*
需要考虑的测试用例:
两个数同号
1)同为正号 16/4 、4/16
2)同为负号 -16/(-4),(-4)/(-16)
两个数为异号
1)(-16)/4,(-16)/32 分子为负数
2)16/(-4) ,16/(-32)
分子分母为零的情况。
如果除数是0,被除数是非零自然数时,商不存在.这是由于任何数乘0都不会得出非零自然数.
如果被除数、除数都等于0,在这种情况下,商不唯一,可以是任何数.这是由于任何数乘0都等于0.
虽然有这么的测试用例,可以这样转换,
将两个数都变成正数来解此题。
*/
int divide(int dividend, int divisor) {
if(divisor==0&÷nd>0){
return INT_MAX;
}
if(divisor==0&÷nd<0){
return INT_MIN;
}
//这里将0/0=0来考虑。
if(dividend==0){
return 0;
}
int symbol_1=1;
int symbol_2=1;
//将两个数都变为正数
if(dividend<0){
symbol_1=-1;
dividend=-dividend;
}
if(divisor<0){
symbol_2=-1;
divisor=-divisor;
}
if(divisor>dividend){//除数的绝对值大于被除数的绝对值
return 0;
}
if(divisor==dividend){
return symbol_1==symbol_2?1:-1;
}
//除数的绝对值小于等于被除数的绝对值
if(divisor==1){
return symbol_1==symbol_2?dividend:-dividend;
}
int diff=dividend-divisor;
int result=1;
while(diff>divisor){
result++;
diff=diff-divisor;
}
return symbol_1==symbol_2?result:-result;//符号相同输出为result,否则输出-result;
}
报超时错误,如下:
思路二
此种思路来源于
https://leetcode.com/discuss/43313/32-times-bit-shift-operation-in-c-with-o-1-solution;
我刚开始也想到了要利用级数来进行求解,但是我不是讲结果展开为幂级数,而是将除数展开为幂级数,因此,写了下代码还是不行,还是报超时错误。
下面的思路确实很好,别人怎么这么聪明了,自己就是想不到,这应该就是差距吧。
具体思路如下:
we assure the factor ret's binary fomula is
ret = a0 + a1*2 + a2*2^2 + ...... + a29*2^29 + a30*2^30 + a31*2^31; ai = 0 or 1, i = 0......31
the dividend B and divisor A is non-negative, then
A(a0 + a1*2 + a2*2^2 + ...... + a29*2^29 + a30*2^30 + a31*2^31) = B; Eq1
(1) when Eq1 divided by 2^31, we can get A*a31 = B>>31; then a31 = (B>>31)/A;
if (B>>31) > A, then a31 = 1; else a31 = 0;
(2) when Eq1 divided by 2^30, we can get A*a30 + A*a30*2 = B>>30; then a30 = ((B>>30) - a30*A*2)/A; and (B>>30) - a31*A*2 can be rewritten by (B-a31*A<<31)>>30, so we make B' = B-a31*A<<31, the formula simplified to a30 = (B'>>30)/A
if (B'>>31) > A, then a30 = 1; else a30 = 0;
(3) in the same reason, we can get a29 = ((B-a31*A<<31-a30*A<<30)>>29)/A, we make B'' = B' - a30*A<<30, the formula simplified to a29 = (B''>>29)/A;
do the same bit operation 32 times, we can get a31 ..... a0, so we get the ret finally.
the C solution with constant time complexity
根据上面的思路实现的代码如下:
int divide(int dividend, int divisor) {
if(divisor==0||(dividend==INT_MIN&&divisor==-1)){//这两种情况产生溢出
return INT_MAX;
}
if(dividend==0){
return 0;
}
bool flag=(dividend>0)^(divisor>0);//用来标识两个数的符号是否是相同的。,相同就为false。
//将两个数都变为正数
unsigned int B=(dividend>0)?dividend:-dividend;
unsigned int A=(divisor>0)?divisor:-divisor;
int result=0;
for(int i=31;i>=0;i--){
if((B>>i)>=A){
result=(result<<1)|0x01;//移位之后在低位添加一个1
//更新B
B-=(A<<i);
}
else{
result=(result<<1);
}
}
return flag?-result:result;
}