Leetcode(50):Pow(x, n)

我们先考虑n是非负数的情况:


方法一:迭代法

double pow(double x, int n)
{
    int i;
    double sum = 1;
    for (i = 0; i < n; i++)
        sum *= x;
    return sum;
}

主要操作为乘法运算。

T(n) = n;

时间复杂度为O(n);


方法二:递归一

double pow(double x, int n)
{
    if (n == 0)
        return 1;
    if (n == 1)
        return x;
    else
        return  pow(x, n-1) * x;
}

主要操作为乘法运算。

T(n) = T(n-1) + 1;

T(1) = 0;

T(n) = n-1;

时间复杂度为O(n);


方法三:递归二(使用二分法)

double pow(double x, int n)
{
    if (n == 0)
        return 1;
    if (n == 1)
        return x;
    if (n % 2)
        return pow(x, n-1) * x; //也可以使用return pow(x, (n-1)/2) * pow(x, (n-1)/2) * x; 结果时间复杂度相同。
    else
        return pow(x, n/2) * pow(x, n/2);
}
主要操作为乘法运算。

先计算n为偶数的时间复杂度:

T(n)= 2T(n/2) + 1;

T(1) = 0;

T(2^k) = 2*T(2^(k-1)) + 1 = 2*(2*T(2^(k-2) + 1)) + 1 = 2^2 * T(2^(k-2)) + 2^1 + 1;

迭代可求得,T(2^k)= 2^k * T(2^0) + 2^(k-1) + 1;

T(n) = n/2 + 1;

时间复杂度为O(n);

n位奇数时的时间复杂度为:

T(n) = T(n-1) + 1;

因为n为奇数,那么n-1一定为偶数,所以T(n)= (n-1)/2 + 2 = n + 3/2;

时间复杂度为O(n);

所以,总的时间复杂度为O(n);


方法四:(递归,二分法,优化)

double pow(double x, int n)
{
    if (n == 0) return 1;
    if (n == 1) return x;
    double v = pow(x, n/2);
    if (n % 2)
        return v * v *x;
    else
        return v * v;
}

基本运算为乘法运算。

n为偶数时:T(n) = T(n/2) + 1;

n为奇数时:T(n) = T(n/2) + 2;

T(1) = 0;

使用上面类似的分析方法可得出时间复杂度为O(logn);


方法五:进一步优化

double pow(double x, int n)
{
    if (n == 0) return 1;
    if (n == 1) return x;
    if (n % 2) 
        return pow(x*x, n/2) * x;
    else
        return pow(x*x, n/2);
}
虽然这个算法的时间复杂度仍然是O(logn)。但是相对于方法三,速度会加快。


接着,考虑n为负数的情况

double myPow(double x, int n)
{
    if (n < 0)
        return 1.0/pow(x, -n);
    else
        return pow(x, n);
}
经过测试,除了方法一时间超时外,其他的都可以Accept。可见leetcode对时间复杂度的要求不是非常严格。


要考虑 0次方的问题

0的0次方有争议, 我们返回0

0的负数次方非法

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013684730/article/details/46828891
文章标签: leetcode C语言
个人分类: Leetcode
上一篇qsort详解
下一篇centos7安装opencl环境
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭