递归(快速幂)(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 类型,直接相乘即可,无需特殊处理。。

相关推荐
会周易的程序员几秒前
aiDgeScanner 工业设备网络扫描与管理工具
网络·c++·物联网·架构·electron·node.js·iot
叼烟扛炮13 分钟前
C++ 知识点17 友元
开发语言·c++·算法·友员
计算机安禾21 分钟前
【c++面向对象编程】第2篇:类与对象(一):定义第一个类——成员变量与成员函数
开发语言·c++
richard_yuu30 分钟前
数据结构|二叉树高阶进阶-经典算法
数据结构·c++·算法
不知名的忻38 分钟前
Dijkstra算法(朴素版&堆优化版)
java·数据结构·算法··dijkstra算法
兩尛1 小时前
c++知识点5
开发语言·c++
澈2071 小时前
C++内存管理:new/delete与内存泄漏实战
开发语言·c++·内存分区
星星码️1 小时前
LeetCode刷题简单篇之反转字母
c++·算法·leetcode
其实防守也摸鱼1 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
naturerun1 小时前
螺旋形遍历奇数阶矩阵
c++·算法·矩阵