当前位置: 首页 > article >正文

【递归】——五道经典链表与递归问题的深度解析

文章目录

  • 面试题08.06.汉诺塔问题
  • 合并两个有序链表
  • 反转链表
  • 两两交换链表中的节点
  • Pow(x,n)

面试题08.06.汉诺塔问题

在这里插入图片描述
在这里插入图片描述
解题思路:

我们可以使用递归的方法将问题分解为更小的子问题。
对于 n 个盘子,移动过程如下:
移动上 n-1 个盘子:将顶部的 n-1 个盘子从源柱子(a)移动到辅助柱子(b),使用目标柱子(c)作为辅助。
移动第 n 个盘子:将底部的第 n 个盘子从源柱子(a)直接移动到目标柱子(c)。
移动 n-1 个盘子到目标柱子:将之前移动到辅助柱子(b)的 n-1 个盘子移动到目标柱子(c),使用源柱子(a)作为辅助。

class Solution 
{
public:
    void dfs(vector<int>& a, vector<int>& b, vector<int>& c, int n)
    {
        // 基本情况:如果只有一个盘子,直接将其从初始柱子移动到结果柱子
        if (n == 1)
        {
            c.push_back(a.back()); // 将初始柱子a的最后一个盘子移动到结果柱子c
            a.pop_back(); // 移除初始柱子a上的盘子
            return; // 返回,结束当前递归
        }

        // 递归步骤:
        // 1. 将前n-1个盘子从初始柱子a移动到辅助柱子b
        dfs(a, c, b, n - 1);
        
        // 2. 将第n个盘子从初始柱子a移动到结果柱子c
        c.push_back(a.back()); // 移动最后一个盘子到结果柱子c
        a.pop_back(); // 移除初始柱子a上的盘子
        
        // 3. 将n-1个盘子从辅助柱子b移动到结果柱子c
        dfs(b, a, c, n - 1);
    }

    void hanota(vector<int>& a, vector<int>& b, vector<int>& c) 
    {
        int n = a.size(); // 获取初始柱子a上盘子的数量
        dfs(a, b, c, n); // 调用DFS函数进行移动
    }
};

合并两个有序链表

在这里插入图片描述
解题思路:

合并两个有序链表的思路是:首先处理基本情况,如果链表 l1 为空,直接返回 l2;如果 l2 为空,直接返回 l1。接着比较两个链表当前节点的值,选择值较小的节点作为合并结果的一部分,并递归地合并剩余的节点。最终,返回合并后的链表头节点。这种方法确保了新链表的顺序性。

class Solution 
{
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) 
    {
        // 如果第一个链表为空,返回第二个链表
        if (l1 == nullptr) return l2;
        // 如果第二个链表为空,返回第一个链表
        if (l2 == nullptr) return l1;

        // 比较两个链表的当前节点值
        if (l1->val <= l2->val)
        {
            // 将l1的当前节点连接到合并结果中,并递归合并l1的下一个节点和l2
            l1->next = mergeTwoLists(l1->next, l2);
            return l1; // 返回当前节点l1
        }
        else
        {
            // 将l2的当前节点连接到合并结果中,并递归合并l1和l2的下一个节点
            l2->next = mergeTwoLists(l1, l2->next);
            return l2; // 返回当前节点l2
        }
    }
};

反转链表

在这里插入图片描述
递归地反转链表的剩余部分,即调用反转函数处理 head->next。
在返回的过程中,将当前节点的 next 指针指向自己,形成反转的链接。
将当前节点的 next 指针设置为 nullptr,使其成为新的链表尾部。

class Solution 
{
public:
    ListNode* reverseList(ListNode* head) 
    {
        // 基本情况:如果链表为空或只有一个节点,直接返回头节点
        if (!head || !head->next)
            return head;

        // 递归反转后续链表
        ListNode* newhead = reverseList(head->next);
        
        // 反转当前节点与下一个节点的指针
        head->next->next = head; // 将当前节点指向前一个节点
        head->next = nullptr; // 当前节点的next设为nullptr,成为新链表的尾部

        return newhead; // 返回反转后的链表头节点
    }
};

两两交换链表中的节点

在这里插入图片描述
检查链表是否为空(head 为 nullptr)或只有一个节点(head->next 为 nullptr)。如果是,直接返回 head,因为没有需要交换的节点。
保存当前节点的下一个节点 (head->next) 为 ret,这将成为新的头节点。
递归调用 swapPairs 函数,处理当前节点之后的节点,得到交换后的结果。
将 head 的下一个节点的 next 指针指向当前节点 (head),完成一对节点的交换。
将当前节点的 next 指针指向递归返回的结果,这样形成新的链表结构。
最终返回 ret,即新的头节点,形成新的成对交换链表。

class Solution 
{
public:
    ListNode* swapPairs(ListNode* head) 
    {
        // 基本情况:如果链表为空或只有一个节点,直接返回头节点
        if (head == nullptr || head->next == nullptr) return head;

        // ret保存当前成对交换后的新头节点
        ListNode* ret = head->next; 
        
        // 递归交换后续节点的成对
        ListNode* newnode = swapPairs(head->next->next);
        
        // 进行成对交换
        head->next->next = head; // 将当前节点的下一个节点指向当前节点
        head->next = newnode; // 将当前节点的next指向交换后的节点

        return ret; // 返回新头节点
    }
};

Pow(x,n)

在这里插入图片描述
处理负指数:

首先检查指数 n 的符号。如果 n 小于 0,则将其转为正数,并计算 x 的绝对值的 n 次方,然后取其倒数,返回 1.0 / ret。
递归计算:

对于非负的 n,调用辅助函数 Pow(x, n) 进行计算。
在 Pow 函数中,首先处理基本情况:如果 n 为 0,返回 1(任何数的 0 次方为 1)。
分治法:

使用递归将问题分解:
计算 x 的 n / 2 次方,保存结果为 tmp。
如果 n 为偶数,结果为 tmp * tmp;如果 n 为奇数,结果为 tmp * tmp * x。
返回结果:

最终,返回计算得到的结果,完成 x 的 n 次方计算。

class Solution 
{
public:
    double myPow(double x, int n) 
    {
        // 处理负指数的情况
        if (n < 0) 
        {
            double ret = Pow(x, -(long long)n); // 使用正指数计算
            return 1.0 / ret; // 返回结果的倒数
        }
        return Pow(x, n); // 直接计算正指数的情况
    }

    double Pow(double x, long long n)
    {
        // 基本情况:任何数的 0 次方为 1
        if (n == 0) return 1;

        // 递归计算 x 的 n/2 次方
        double tmp = Pow(x, n / 2);
        
        // 如果 n 为偶数,返回 tmp 的平方;如果为奇数,返回 tmp 的平方乘以 x
        return (n % 2 == 0) ? tmp * tmp : tmp * tmp * x;
    }
};

http://www.kler.cn/a/380234.html

相关文章:

  • sparkSQL面试题
  • react18中redux-promise搭配redux-thunk完美简化异步数据操作
  • 使用NCNN在树莓派部署深度学习模型流程
  • 【Python】【数据可视化】【商务智能方法与应用】课程 作业一 飞桨AI Studio
  • 智慧汇聚:十款企业培训工具打造学习型企业
  • 杂货 | 每日资讯 | 2024.11.1
  • stuid学生信息
  • 第十二章 spring Boot+shiro权限管理
  • 【django】django RESTFramework前后端分离框架快速入门
  • 一阶 RC 低通滤波器实验方案
  • MFC图形函数学习05——画椭圆函数
  • 推荐一款高级的安装程序打包工具:Advanced Installer Architect
  • 用Python遍历输出烟感名称和状态
  • 简单说明vuex
  • AIDOVECL数据集:包含超过15000张AI生成的车辆图像数据集,目的解决旨在解决眼水平分类和定位问题。
  • SwiftUI:单个App支持设置多语言
  • 【零基础学习CAPL】——使用CAP测试报文长度DLC
  • 交换机的基本配置
  • MySql创建用户与授权
  • 关于安科瑞电能质量监测和治理产品在分布式光伏电站的应用探讨
  • 又一次安装autoware.universe的过程
  • 苏州金龙新V系客车创新引领旅游出行未来
  • 计算机网络面试题三道之二
  • 【人工智能】自动化机器学习的实现:使用Python与AutoML工具进行模型自动化调参
  • 提升大数据量分页查询性能:深分页优化全解
  • 深度学习基础知识-残差网络ResNet