码迷,mamicode.com
首页 > 其他好文 > 详细

【leetcode 分治法】Pow(x, n)与Sqrt(x)函数的实现

时间:2014-11-22 09:21:59      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:leetcode   分治法   pow   sqrt   

</pre>Pow(x, n)</h1><h1><span style="color:#3333ff;">1、分析</span></h1><div><span style="font-size:18px;">函数原型double pow(double x, int n),实现求x的n次方。</span></div><div><span style="font-size:18px;"></span></div><div><span style="font-size:18px;">有一点需要注意:int n类型范围 -2147483648~2147483647当n=-2147483648,则-n=2147483648超出2147483647,结果仍然是-2147483648,所以应该单独处理。</span></div><div><span style="font-size:18px;">也可以用机器码来解释这一个知识点:-2147483648的机器吗为1000...0000(32位),取负,即机器码各位取反后加1,得到的还是100....000。这也是代码中if(n<0 && n!=INT_MIN) return 1.0/pow(x,-n) 为什么这样写的原因,如果写成if(n<0) return 1.0/pow(x,-n) 则会造成死循环</span></div><h1><span style="color:#3333ff;">2、正解代码</span></h1><div><span style="font-size:18px;">分治法</span></div><div><pre name="code" class="cpp"><span style="font-size:18px;">class Solution {
public:
    double pow(double x, int n) {
        if(n<0 && n!=INT_MIN) return 1.0/pow(x,-n);
        else if(n==INT_MIN) {double val=pow(x,-(n/2)); return 1.0/val*val;}
        else if(n==0) return 1.0;
        else if(n%2==1) {double val=pow(x,(n-1)/2);return x*val*val;  }
        else {double val=pow(x,n/2);return val*val;} 
    }
};</span>

3、误解代码

下面的代码超时,因为:
pow(x,n/2)*pow(x,n/2)实际上计算了两次pow(x,n/2),但是正确的算法应该是计算出pow(x,n/2)后,赋给val,然后val*val,只计算一次pow(x,n/2)。下面的程序每一处都是pow()*pow(),这样一来跟x*x*x*x....一个一个乘没什么不同。
double pow(double x, int n) {
        if(n<0 && n!=INT_MIN) return 1.0/pow(x,-n);
        else if(n==INT_MIN) return 1.0/(pow(x,-(n/2))*pow(x,-(n/2)));
        else if(n==0) return 1.0;
        else if(n%2==1) return x*pow(x,(n-1)/2)*pow(x,(n-1)/2);  
        else return pow(x,n/2)*pow(x,n/2);    




Sqrt(x)

1、分析

函数原型 int sqrt(int x),实现求x的平方根。
几点注意:
#1 math头文件里的是double sqrt(double)等三种版本,leetcode上要实现的是int sqrt(int x),还是不同的

#2 int sqrt(int x)结果是向下取整的,比如sqrt(10)等于3,故我们要寻找的是1~x中最后一个满足val*val<x的那个数 

#3 用二分查找法(先参见下面代码)
取1~x的中点mid,若mid*mid>x,那么根应该在1~mid-1之间,如果mid*mid<x,那么根应该在mid+1~x之间,若mid*mid==x则直接输出mid;
当然,在果mid*mid<x的情况下,根可能就是mid,但是我们仍然假设根在mid+1~x之间,程序运行下去会发现,mid+1~x的所有数的平方都大于x,最后while退出时first、last都等于mid+1,故while退出要处理,这就是if语句的一个作用

#4 考虑溢出问题
因为mid为int类型,所以mid*mid是有可能溢出的,应该声明为long long类型。
如果限定只能用int类型,那么可以将mid*mid<x 写成 mid<x/mid ,这样肯定不会溢出

2、代码

分治法,二分查找
<span style="font-size:18px;">class Solution {
public:
    int sqrt(int x) {  //x不会小于0
        if(x==0) return 0;
        long long int first=1,last=x;
        while(first<last){
            long long int mid=(first+last)/2;  
            if(mid*mid<x) first=mid+1;     //long long类型与int类型比较,int被暂时当作long long?
            else if(mid*mid>x) last=mid-1;
            else return mid;
        }
        if(first*first>x) return first-1;
        else return first;
        
    }
};</span>



【leetcode 分治法】Pow(x, n)与Sqrt(x)函数的实现

标签:leetcode   分治法   pow   sqrt   

原文地址:http://blog.csdn.net/u012162613/article/details/41361655

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!