Pow(x,n)的O(logN)时间复杂度实现

题目描述

实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:

输入: 2.00000, 10
输出: 1024.00000
示例 2:

输入: 2.10000, 3
输出: 9.26100
示例 3:

输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25

说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。

题目分析

这道题其实很简单,最容易想到的方法就是通过n此循环x*=x最终来得出答案,不过可想而知,这样是非常低效的,时间复杂度为O(N),那么如何改进这个算法呢?很简单,我们知道X^n是可以拆分的,即当n为偶数时,X ^n=X ^(n/2)*X ^(n/2),当n为奇数时,X ^n=X ^((n-1)/2)*X ^((n-1)/2)*X,很显然,这个式子不管n是正数还是负数都是成立的。这样就能写出递归部分的代码了:
if(n%2==0)return myPow(x,n/2)*myPow(x,n/2);
else return myPow(x,(n-1)/2)*myPow(x,(n-1)/2)*x;
再将边界条件加上,即可得出以下代码:

class Solution {
public:
    double myPow(double x, int n) {
        if(x==0)return 0;
        if(n==1)return x;
        if(n==0)return 1;
        if(n==-1)return 1.0/x;
        
        if(n%2==0)return myPow(x,n/2)*myPow(x,n/2);
        else return myPow(x,(n-1)/2)*myPow(x,(n-1)/2)*x;
        return 0;
    }
};

很明显,这样的算法复杂度是O(logN)的,不过实际上算法复杂度是O(2logN)的,因为每次递归时都会调用两次相同的递归函数,很明显这样是很不必要的,可以直接将一次调用结果保存即可,对算法进行优化如下:

class Solution {
public:
    double myPow(double x, int n) {
        if(x==0)return 0;
        if(n==1)return x;
        if(n==0)return 1;
        if(n==-1)return 1.0/x;
        
        if(n%2==0)
        {
            double temp=myPow(x,n/2);
            return temp*temp;
        }
        else 
        {
            double temp=myPow(x,(n-1)/2);
            return temp*temp*x;
        }
        return 0;
    }
};

由优化后的算法可知,算法复杂度降低到了O(logN)

你可能感兴趣的:(LeetCode)