一、题目描述
实现 pow(x, n) ,即计算 x 的整数 n 次幂函数。
double myPow(double x, int n);
示例:
示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3
输出:9.26100
示例 3:
输入:x = 2.00000, n = -2
输出:0.25000
解释:2^-2 = 1/2^2 = 1/4 = 0.25
提示:
-100.0 < x < 100.0
-2^31 <= n <= 2^31 - 1
二、解题思路
如果直接循环计算:
x * x * x * x ... (n次)
时间复杂度是:
O(n)
当 n 很大时效率会非常低。
因此需要使用 快速幂(Binary Exponentiation)。
核心思想:
x^10
10 的二进制 = 1010
x^10 = x^8 * x^2
计算时不断:
底数平方
指数除2
例如:
x^10
10 = 1010
x^10
= x^8 * x^2
通过二进制拆分,可以把复杂度降到:
O(log n)
三、注意的坑
1 指数可能为负数
例如:
x^-2 = 1 / x^2
因此需要先处理:
if(n < 0)
{
x = 1/x;
n = -n;
}
2 INT_MIN 溢出问题
当:
n = -2147483648
执行:
-n
会溢出。
解决方法:
使用 long long
四、方法一:快速幂(迭代实现)
算法步骤
循环过程中:
如果当前二进制位为1 -> 乘入结果
底数平方
指数右移
例如:
n = 10
二进制:1010
计算过程:
| n | result | x |
|---|---|---|
| 10 | 1 | 2 |
| 5 | 1 | 4 |
| 2 | 4 | 16 |
| 1 | 4 | 256 |
| 0 | 1024 | 65536 |
C语言代码
double myPow(double x, int n)
{
long long N = n;
if(N < 0)
{
x = 1 / x;
N = -N;
}
double result = 1.0;
while(N > 0)
{
if(N & 1)
{
result *= x;
}
x *= x;
N >>= 1;
}
return result;
}
五、方法二:递归快速幂
利用递归思想:
x^n = (x^(n/2))^2
如果 n 为奇数:
x^n = (x^(n/2))^2 * x
C语言实现
double fastPow(double x, long long n)
{
if(n == 0)
return 1;
double half = fastPow(x, n / 2);
if(n % 2 == 0)
return half * half;
else
return half * half * x;
}
double myPow(double x, int n)
{
long long N = n;
if(N < 0)
return 1 / fastPow(x, -N);
return fastPow(x, N);
}
六、复杂度分析
时间复杂度:
O(log n)
因为每次指数都:
n / 2
空间复杂度:
迭代:O(1)
递归:O(log n)
七、总结
本题核心是 快速幂算法,关键点有三个:
1️⃣ 指数转二进制计算
2️⃣ 处理负指数
3️⃣ 防止 INT_MIN 溢出
快速幂在很多题目中都会出现,例如:
50. Pow(x,n)
191. 位1的个数
190. 颠倒二进制位
231. 2的幂
342. 4的幂
是 算法面试高频技巧之一。