在做leetcode题目Sqrt的时候,使用分治法时,要比较mid的平方与x的大小关系,如果mid的平方比x大,那么right=mid-1,如果小,left=mid+1,在这种方式下,需要求mid的平方,mid的平方可能会超出Integer的范围,这就出现了溢出的问题,仔细想一下,需要求平方吗?完全可以避免!。
比较Math.pow(mid,2)与x的大小,完全可以用mid与x/mid的比较代替,这是小学数学就能掌握的问题。
在二分法过程中还有可能出现溢出的情况是mid=(left+right)/2,如果left+right的和超过了整数范围完全可能溢出,怎么办?
稍微变化一下(left+right)/2 = left+(right-left)/2,这样就不会溢出了!
看来做题的时候动动脑子就能解决一些问题,
下面是处理Sqrt的代码(二分法):
public int mySqrt(int x) {
if(x <= 0) return 0;
int r = x/2+1;
int l = 1;
int mid=0;
while(l<=r){
mid = (l+r)/2;
if(mid==x/mid){
return mid;
}else if(mid>x/mid){
r = mid-1;
}else{
l = mid+1;
}
}
if(Math.pow(mid, 2)>x){
return mid-1;
}
return mid;
}
有时候我们也可以使用BigInteger来处理溢出,本来以为这是杀手锏,可以解决一切问题,但是leetcode竟然不认识BigInteger,下面是使用BigInteger解决的代码:
public int mySqrtUseBigInteger(int x) {
BigInteger xb = new BigInteger(x+"");
BigInteger r = new BigInteger((x/2+1)+"");
BigInteger l = new BigInteger("0");
BigInteger mid = new BigInteger("0");
BigInteger two = new BigInteger("2");
BigInteger one = new BigInteger("1");
while(l.compareTo(r)<0 || l.compareTo(r)==0){
mid = (l.add(r)).divide(two);
BigInteger pow = mid.multiply(mid);
if(pow.compareTo(xb)==0){
return mid.intValue();
}else if(pow.compareTo(xb)>0){
r = mid.subtract(one);
}else{
l = mid.add(one);
}
}
if(mid.multiply(mid).compareTo(xb)>0){
return mid.intValue()-1;
}
return mid.intValue();
}