F_G

许多问题需要说清楚就可以&&走永远比跑来的重要

导航

[Leetcode] Divide Two Integers

大体的思想史使用折半。

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

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

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

我的代码如下。

 1 public class Solution {
 2     public int divide(int a, int b) {
 3         double dividend = a;
 4         double divisor =b;
 5         //////////////////////////very good corner case below
 6         /*
 7             我们知道负整数比正整数多了一个状态。两者的绝对值相差是一,但是如果使用这个负整数*-1,结果是得到了最大的正整数。但是我们按照常规的将两者转化为
 8             正数在进行计算的方式,会溢出。因为最小的负数,转化为正数时,就已经超了。我们可以将其存在一个double当中,但是最后转化为int是也是会溢出的。
 9             所以这是一个非常好的Corner case
10             如果a是最小的负整数,也就是Integer.MIN_INT
11         */
12         if(Math.abs(b)==1){
13             if(b>0) return a;//1
14             else{//-1
15                 if(a>0){
16                     return 0-a;
17                 }else if(a==Integer.MIN_VALUE){
18                     return Integer.MAX_VALUE;
19                 }else{
20                     return a*b;
21                 }
22             }
23         }
24         ////////////////////////very good corner case up
25         if(divisor==0||divisor==0) return 0;
26         int flag = dividend*divisor<0? -1:1;
27         
28         dividend = Math.abs(dividend);
29         divisor = Math.abs(divisor);
30         
31         int sum=0;
32         
33         while(dividend!=0){
34             if(dividend<divisor){
35                 return sum*flag;
36             }
37             //assure there at least one 
38             double pre=divisor;
39             int precount=1;
40             double tmp=divisor;
41             while(tmp+tmp<dividend){
42                 pre=tmp+tmp;
43                 tmp+=tmp;
44                 precount=precount+precount;
45             }
46             
47             if(tmp+tmp==dividend){
48                 return (precount+precount)*flag;
49             }
50             dividend=dividend-tmp;
51             sum=sum+precount;
52         }
53         return (int)(sum*flag);
54     }
55 }

 

posted on 2015-08-14 21:37  F_G  阅读(169)  评论(0编辑  收藏  举报