递归(快速幂)(5)

https://blog.csdn.net/2601_95366422/article/details/159202641

上节课链接

一.题目

50. Pow(x, n) - 力扣(LeetCode)

二.思路讲解

2.1 找到递归

本题要求实现 xn 次幂 。我们可以通过递归分治 来高效计算。例如,求 216 次方,可以分解为 2^8 * 2^8,而 2^8 又可以分解为 2^4 * 2^4,如此反复,直到 2^0 = 1。这就是典型的快速幂 思想。但需要注意,当 n 为奇数时,比如 2^5,可以分解为 2^2 * 2^2 * 2,即多乘一个 x。因此,递归的规律就是:每次将指数减半,根据奇偶性决定是否多乘一次底数

2.2 子问题解决

明确了递归规律,子问题的解决就清晰了:我们定义一个递归函数 myPow(x, n),它计算 xn 次幂。在递归过程中:

  • 先递归求出 x^(n/2) 的值,记为 half

  • 如果 n 是偶数,则结果为 half * half

  • 如果 n 是奇数,则结果为 half * half * x

2.3 递归的终止条件

递归的终止条件是当 n == 0 时,任何数的 0 次幂都等于 1 ,直接返回 1。这是递归的基础情况,也是递归能够结束的关键。

2.4 细节问题
  • 负指数处理 :如果 n 为负数,我们可以先计算 x|n| 次幂,然后取倒数,即 1 / myPow(x, -n)。但这里有一个边界陷阱 :当 n最小负整数 (如 -2^31)时,取相反数会超出 int 范围,导致溢出。因此,需要将 n 转换为 long long 类型来处理。

  • 底数为 0 的情况 :当 x == 0n <= 0 时,需要处理除零异常,但题目通常保证输入有效。

  • 精度问题 :由于结果是浮点数,直接递归计算即可,注意使用 double 类型。

三.代码演示

cpp 复制代码
class Solution 
{
public:
    double myPow(double x, int n) 
    {
        long long t = (long long)n;//避免最小负数不能转成正数
        if(n < 0)
        {
            return 1 / pow(x,-t);
        }    
        else
            return pow(x,t);
    }
    double pow(double x,long long n)
    {
        if(n == 0)
            return 1.0;
        double tmp = myPow(x,n/2);//获取下一次值
        return n % 2 == 0 ? tmp * tmp : tmp * tmp * x; 
    }
};

四.代码讲解

一、主函数处理负指数

在公开接口 myPow 中,首先需要处理指数 n 可能为负数的情况。由于负指数运算等价于正指数结果的倒数,因此我们将 n 转换为 long long 类型 t,以避免最小负数(如 -2^31)取相反数时溢出。若 n < 0,则返回 1 / pow(x, -t),即先计算正指数的幂,再取倒数;否则直接调用 pow(x, t) 计算正指数幂。这样,主函数负责符号处理溢出保护,将问题统一转化为正指数计算。

二、递归函数设计

辅助函数 pow(double x, long long n) 专门用于计算 x 的非负整数次幂。它采用递归分治 的思想:每次将指数 n 除以 2,先求出 x^(n/2) 的值,再根据 n 的奇偶性决定如何组合。这个函数的返回值就是 xn 次幂。

三、递归终止条件

递归的终止条件是当 n == 0 时,任何数的 0 次幂都等于 1.0 ,直接返回 1.0。这是递归的基础情况,也是递归能够层层返回的关键。

四、递归步骤分解

对于 n > 0 的情况,递归步骤如下:

  1. 递归获取子结果 调用 myPow(x, n/2) 得到 x^(n/2) 的值,记为 tmp。注意这里 myPow 会再次进入主函数,但由于 n/2 是正数,它会再次调用 pow,从而形成递归链。这一步骤我们无需关心内部细节,只需相信它能正确返回子结果。

  2. 根据奇偶性组合结果

    • 如果 n 是偶数,则 x^n = tmp * tmp,直接返回两者的乘积。

    • 如果 n 是奇数,则 x^n = tmp * tmp * x,即再多乘一个 x

这样,每次递归都将指数减半,时间复杂度为 O(log n)

五、关键细节
  • 类型转换与溢出保护 :将 int 类型的 n 转换为 long long 后再取相反数,避免了最小负数溢出问题。

  • 递归的信任 :在 pow 函数中调用 myPow 时,我们相信它能正确处理子问题,尽管两者互相调用,但逻辑上是自洽的。

  • 奇偶判断 :通过 n % 2 判断奇偶性,决定是否多乘一次 x

  • 终止条件的准确性 :当 n == 0 时直接返回 1.0,这是递归的出口。

  • 浮点数运算 :结果使用 double 类型,直接相乘即可,无需特殊处理。。

相关推荐
小江的记录本4 小时前
【分布式】分布式核心组件——分布式ID生成:雪花算法、号段模式、美团Leaf、百度UidGenerator、时钟回拨解决方案
分布式·后端·算法·缓存·性能优化·架构·系统架构
大江东去浪淘尽千古风流人物5 小时前
【cuVSLAM】GPU 加速、多相机、实时视觉/视觉惯性 SLAM设计优势
c++·人工智能·数码相机·ubuntu·计算机视觉·augmented reality
自信1504130575911 小时前
重生之从0开始学习c++之模板初级
c++·学习
leobertlan11 小时前
好玩系列:用20元实现快乐保存器
android·人工智能·算法
青梅橘子皮11 小时前
C语言---指针的应用以及一些面试题
c语言·开发语言·算法
历程里程碑11 小时前
2. Git版本回退全攻略:轻松掌握代码时光机
大数据·c++·git·elasticsearch·搜索引擎·github·全文检索
极客智造11 小时前
深度解析 C++ 类继承与多态:面向对象编程的核心
c++
_深海凉_12 小时前
LeetCode热题100-有效的括号
linux·算法·leetcode
零号全栈寒江独钓14 小时前
基于c/c++实现linux/windows跨平台获取ntp网络时间戳
linux·c语言·c++·windows