LeetCode 50. Pow(x, n)(快速幂详解 | C语言实现)

一、题目描述

实现 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的幂

算法面试高频技巧之一


相关推荐
renhongxia117 小时前
世界模型,是“空中楼阁”还是AGI的“最后一块拼图”?
运维·服务器·数据库·人工智能·算法·agi
G.O.G.O.G17 小时前
LeetCode SQL 从入门到精通(MySQL)06(上)
数据库·sql·mysql·leetcode
zephyr0519 小时前
动态规划-最长上升子序列问题
算法·动态规划
闪电悠米19 小时前
力扣hot100-56.合并区间-排序详解
数据结构·算法·leetcode·贪心算法·排序算法
openKylin19 小时前
与全球技术演进同频,openKylin 3.0从C迈向Rust
c语言·开发语言·rust·开源·开放原子·openkylin
迷茫、Peanut20 小时前
C语言sizeof和strlen
c语言
卡提西亚21 小时前
leetcode-1438. 绝对差不超过限制的最长连续子数组
算法·leetcode·职场和发展
Java面试题总结21 小时前
LeetCode 93.复原IP地址
算法·leetcode·职场和发展·.net
从零开始的代码生活_21 小时前
C++ 多态详解:虚函数、动态绑定、抽象类与虚表原理
开发语言·c++·后端·学习·算法
泷寂1 天前
最小生成树 (MST基础)
算法