leetcode算法总结 —— 快速幂算法


参考的是大神的文章,这篇文章相当好
https://blog.csdn.net/qq_19782019/article/details/85621386

1. 引出快速幂算法

3 ^ 10 = 3*3*3*3*3*3*3*3*3*3计算这个我们可以循环乘3但是时间复杂度为O(N)
那么我们可以用3 ^ 10 = 9 ^ 5来简化计算
此时指数由10缩减一半变成了5,而底数变成了原来的平方,求3^10原本需要执行10次循环操作,求9 ^ 5却只需要执行5次循环操作

例如2 ^ 10000 = 4 ^ 5000 底数只是做了一个小小的平方操作,而指数就从10000变成了5000,减少了5000次的循环操作。
所以现在我们的问题是如何把指数5变成原来的一半
另一种方法能表示9 ^ 5
9 ^ 5 =(9 ^ 4)*(9 ^ 1)
这里即为9 ^ 1,这个9 ^ 1 我们先单独移出来,剩下的9 ^ 4又能够在执行“缩指数”操作了,把指数缩小一半,底数执行平方操作
9 ^ 5=(81 ^ 2)* ( 9 ^ 1)
把指数缩小一半,底数执行平方操作
9 ^ 5=(6561 ^ 1)* (9 ^ 1)
接下来我们就可以用代码实现快速幂了。
时间复杂度类似于二分算法,为O(logn) 比之前的时间复杂度O(N)降低很多了

long long fastPower(long long base, long long power)
{
    
    
    long long result = 1;
    while (power > 0)
    {
    
    
        //如果指数为偶数
        if (power % 2 == 0)
        {
    
    
            power = power / 2;  //把指数缩小为一半
            base = base * base; //底数变大成原来的平方
        }
        else
        {
    
                               //如果指数为奇数
            power = power - 1;      //把指数减去1,使其变成一个偶数
            result = result * base; //此时记得要把指数为奇数时分离出来的底数的一次方收集好

            power = power / 2;  //此时指数为偶数,可以继续执行操作
            base = base * base; //底数变大成原来的平方
        }
    }
    return result;
}

2. 简化语句

接下来我们精简代码,简化语句

long long fastPower(long long base, long long power)
{
    
    
    long long result = 1;
    while (power > 0)
    {
    
    
        //当为指数奇数的时候
        if (power % 2 == 1)
        {
    
    
            result = result * base; //收集此时的一次方
        }
        //power减半和power减一减半结果一样,然后base翻倍
        power = power / 2;
        base = (base * base);
    }
    return result;
}

3. 使用位运算来提升性能

long long fastPower(long long base, long long power)
{
    
    
    long long result = 1;
    while (power > 0)
    {
    
    
        if (power & 1)
        {
    
     //此处等价于(power%2==1), power & 1 若为奇数则结果为true
            result = result * base;
        }
        power = power >> 1; //此处等价于power=power/2, 一个数右移power >> 1 一位等于他除以2
        base = (base * base);
    }
    return result;
}

4. 对应leetcode题型

https://leetcode-cn.com/problems/powx-n/
这个题我们直接提取一个快速幂方法,然后考虑一些边界条件即可。

double fastPower(double base, int power)
{
    
    
    double result = 1;
    while (power > 0)
    {
    
    
        if (power & 1)
        {
    
     //此处等价于(power%2==1), power & 1 若为奇数则结果为true
            result = result * base;
        }
        power = power >> 1; //此处等价于power=power/2, 一个数右移power >> 1 一位等于他除以2
        base = (base * base);
    }
    return result;
}
double myPow(double x, int n)
{
    
    
    if (x == 1)
    {
    
    
        return x;
    }
    double result = 1;
    //特殊处理-2147483648,因为将n转正数就会溢出
    if (n == -2147483648)
    {
    
    
        result *= x; //先乘一次, 然后降幂
        n++;         //降幂, 避免溢出
        result = 1 / fastPower(x, -n) * result;
    }
    else if (n < 0 && n != -2147483648)
    {
    
    
        result = 1 / fastPower(x, -n);
    }
    else if (n > 0)
    {
    
    
        result = fastPower(x, n);
    }
    else
    {
    
    
        result = 1;
    }

    return result;
}

猜你喜欢

转载自blog.csdn.net/chongbin007/article/details/106434432