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

递归,搜索,回溯算法(一)

目录

一、递归是什么

二、递归和搜索和回溯算法

专题一、递归

1.汉诺塔问题

2.


一、递归是什么

        每每提到递归,我相信第一秒浮现在大多数人脑海中的都是这几个名词“难”,“复杂”,“看不懂”,“不知道在干什么”,一看到递归二字,内心就止不住的恐惧,笔者第一次大量接触递归是在学习二叉树的时候,看看那时候,的确是一看递归就内心发毛,面对几行简简单单的代码却根本看不懂的那种感觉到现在记忆犹新。

        这也是我为什么要写这篇文章的原因--帮助像我一样对递归有恐惧的人客服恐惧。

        其实学完以后你会发现,递归只有一个核心点,在函数体中套用函数体,关键的关键就是找到重复子问题

在这里我们可以把写递归分为三个境界:

第一境界: 会画递归的展开图。

第二境界:可以拿捏二叉树中的递归。

第三境界:可以宏观看待递归

这里提到重要的一点,“宏观看待递归”,有的读者可能会问,什么叫宏观看待递归?其实就是把递归这个函数体看作一个“黑盒”,我们相信这个黑盒可以完成我们的任务,然后再来编写函数体,这样我们就可以发现写递归非常之简单了。

二、递归和搜索和回溯算法

        在学习二叉树的时候,我们肯定都学过前,中,后序遍历吧,这其实就是一种搜索,细致来说叫做深度优先搜索(DFS),而回溯算法又恰巧要大量使用DFS,所以学好递归,其实就是在为搜索和回溯算法打基础,在整个学习过程中,我们会分为四个专题,由浅入深,细致讲解回溯算法。

专题一、递归

1.汉诺塔问题

题目链接如下

面试题 08.06. 汉诺塔问题 - 力扣(LeetCode)

class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) 
    {
        dfs(A, B, C, A.size());
    }
    void dfs(vector<int>& a, vector<int>& b, vector<int>& c, int n)
    {
        if (n == 1)
        {
            c.push_back(a.back());
            a.pop_back();
            return;
        }
        dfs(a, c, b, n - 1);
        c.push_back(a.back());
        a.pop_back();
        dfs(b, a, c, n - 1);
    }
};

       在这道题中,最小的子问题是一个柱子上的n的盘子借助另一个柱子将n - 1个盘子转移到第三个柱子上,也是我们编写dfs函数的依据。

2.合并两个有序链表

题目链接如下

21. 合并两个有序链表 - 力扣(LeetCode)

class Solution 
{
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) 
    {
        if (l1 == nullptr)
            return l2;
        if (l2 == nullptr)
            return l1;
        if (l1->val >= l2->val)
        {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
        else
        {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        }

    }
};

在这个问题中,函数dfs的作用就是题目,合并俩个有序链表并返回合并后的头节点。

3. 反转链表

题目链接如下

LCR 024. 反转链表 - 力扣(LeetCode)

class Solution 
{
public:
    ListNode* reverseList(ListNode* head) 
    {
        if (head == nullptr || head->next == nullptr)
        {
            return head;
        }
        ListNode* newhead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newhead;
    }
};

4. 两两交换链表中的节点

题目链接如下

24. 两两交换链表中的节点 - 力扣(LeetCode)

class Solution {
public:
    ListNode* swapPairs(ListNode* head) 
    {
        if (head == nullptr || head->next == nullptr)
        {
            return head;
        }
        ListNode* temp = swapPairs(head->next->next);
        ListNode* Next = head->next;
        head->next = temp;
        Next->next = head;
        return Next;
    }
};

5.快速幂

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

class Solution {
public:
    double myPow(double x, int n) 
    {
        return n < 0 ? 1.0 / pow(x, -(long long)n) : pow(x, n);
    }
    double pow (double x, long long n)
    {
        if (n == 0)
        {
            return 1.0;
        }
        double tmp = pow(x, n / 2);
        return n % 2 == 0 ? tmp * tmp : tmp * tmp * x;
    }
};

相关文章:

  • 多版本PHP开发环境配置教程:WAMPServer下MySQL/Apache/MariaDB版本安装与切换
  • ubuntu下docker 安装 graylog 6.1
  • HTML输出流
  • WebMvcConfigurer 的 addResourceLocations
  • Eplan许可管理的自动化工具
  • [Vue2]指令修饰符(一)
  • [问题收集]mysql主从分离过程中,数据不同步可能导致的后果以及应对策略
  • NFC 智能门锁全栈解决方案:移动端、服务器、Web 管理平台
  • src案例分享-逻辑漏洞
  • 软路由用联想j3710主板踩坑
  • 从0到1,解锁Ant Design X的无限可能
  • 能源革命新突破:虚拟电厂赋能微电网智能调控,构建低碳生态新格局
  • MCP插件使用(browser-tools-mcp为例)
  • 通过一个led点灯的demo来熟悉openharmony驱动编写的过程(附带hdf详细调用过程)
  • 【windows搭建lvgl模拟环境之VSCode】
  • Vue3项目中的.vscode文件夹
  • kettle插件-dm达梦数人大金仓Vastbase数据库插件
  • 硬件基础--05_电压
  • RAG优化:Python从零实现分层索引Hierarchy黑科技拯救迷失的文本碎片
  • 寻找力量
  • 奥利弗·斯通回顾越战50周年:我们不善于总结历史教训
  • 扶桑谈|素称清廉的石破茂被曝受贿,日本政坛或掀起倒阁浪潮
  • 中国以“大幅开放市场”回应贸易保护主义
  • 陈丹燕:赤龙含珠
  • 数据中心业务今年预增50%,丹佛斯:中国是全球最重要的市场
  • 网民反映“潜水时遭遇服务质量不佳”,三亚开展核查调查