参考的是大神的文章,这篇文章相当好
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;
}