您的位置:首页 > 其它

[Leetcode] Divide Two Integers

2015-08-14 21:37 399 查看
大体的思想史使用折半。

dividend(被除数) 和 divisor(除数)

除数不断进行翻倍,这里使用加法而不是乘以2的操作,同时记录divisor的个数,同样可以使用加法实现,当大于dividend的时候,停止,并且输出当前统计的divisior的个数。

同时从dividend当中减去当前的对divisor翻倍的值。在此进行下面的while循环,停止条件

一、剩余的dividend为零

二、剩余的dividend小于divisor

这里对divisor为1或者-1的情况进行特殊处理。

但是这里有一个非常好的corner case

如果是divisor是-1,那么只需要对dividend取反就可以了,但是如果dividend是最小的负数,就会出现问题。

因为计算机当中的整数是使用补码表示的,而且负数的状态比正数多了一个,如果进行取反,就会发生很奇怪的事情:

-1*Integer.MIN_VALUE还是Integer.MIN_VALUE

0-Integer.MIN_VALUE也是Integer.MIN_VALUE

因为补码的最小负数表示是

1,000000

上面的乘以-1或者被0减实际上都是取反加一的一种变化,

0,111111 +1

变为

1,000000

所以得不到我们想要的最大值,

因此这样当作一种特殊情况对待

我的代码如下。

public class Solution {
public int divide(int a, int b) {
double dividend = a;
double divisor =b;
//////////////////////////very good corner case below
/*
我们知道负整数比正整数多了一个状态。两者的绝对值相差是一,但是如果使用这个负整数*-1,结果是得到了最大的正整数。但是我们按照常规的将两者转化为
正数在进行计算的方式,会溢出。因为最小的负数,转化为正数时,就已经超了。我们可以将其存在一个double当中,但是最后转化为int是也是会溢出的。
所以这是一个非常好的Corner case
如果a是最小的负整数,也就是Integer.MIN_INT
*/
if(Math.abs(b)==1){
if(b>0) return a;//1
else{//-1
if(a>0){
return 0-a;
}else if(a==Integer.MIN_VALUE){
return Integer.MAX_VALUE;
}else{
return a*b;
}
}
}
////////////////////////very good corner case up
if(divisor==0||divisor==0) return 0;
int flag = dividend*divisor<0? -1:1;

dividend = Math.abs(dividend);
divisor = Math.abs(divisor);

int sum=0;

while(dividend!=0){
if(dividend<divisor){
return sum*flag;
}
//assure there at least one
double pre=divisor;
int precount=1;
double tmp=divisor;
while(tmp+tmp<dividend){
pre=tmp+tmp;
tmp+=tmp;
precount=precount+precount;
}

if(tmp+tmp==dividend){
return (precount+precount)*flag;
}
dividend=dividend-tmp;
sum=sum+precount;
}
return (int)(sum*flag);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: