IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构与算法之对于递归的理解 -> 正文阅读

[数据结构与算法]数据结构与算法之对于递归的理解

对于递归的理解

前言

视频观看更得劲:【小小福讲算法】硅谷工程师十五分钟带你深入理解 Recursion (递归)算法,及其衍生出的算法(分治算法 Divide and Conquer, 回溯 Ba_哔哩哔哩_bilibili


简介

递归是什么

“Recursion is an approach to solving problems using a function that calls itself as a subroutine.” ---- LeetCode

  • 为什么 function 需要 call 自己?

    • 因为大问题(Big problem)可以分解成小问题(sub problems).
    • 小问题通常很容易解答!
    • 例如:跑步 10km 很难,但是跑步 10km =跑步 9km+ 先跑 1km,后者不再是一个艰难的任

递归函数的结构

递归函数由终止条件(Base)和递归关系(Recursion Relation)组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-et323Fer-1663382898115)(assets/image-20220913105939-9cnti01.png)]

举个例子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c8tNiQVj-1663382898117)(assets/image-20220913110041-eetulq6.png)]?

递归在计算机中的实现方法

  • 任何一个函数调用,计算机会在内存中生成一块区域,用于存放函数的参数,返回地址等,这块区域叫做“栈(stack)”
  • 递归函数也是一种函数调用 → 因而也会生成一系列的 stack。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y46CpV1o-1663382898117)(assets/GIF 2022-9-13 11-03-29-20220913110354-og1s27e.gif)]

例题

在二叉搜索树中搜索某一结点

算法步骤可以抽象为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JHN9YOey-1663382898118)(assets/image-20220913110642-14obazj.png)]

?

递归的几种常见形式

Memorization 缓存

如果递归问题会产生重复的子问题,那么可以使用 cache 记住子问题的答案,避免重复计算。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WnBo5o3b-1663382898118)(assets/image-20220913110948-nnwtlle.png)]

例题

  1. 斐波那契数列的计算:剑指 Offer 10- I. 斐波那契数列 - 力扣(LeetCode)
  2. 爬楼梯:70. 爬楼梯 - 力扣(LeetCode)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xfPynYef-1663382898119)(assets/image-20220913111235-qt7hkd0.png)]

Divide And conquer 分治

Divide and Conquer 分而治之,几乎等同于标准的 Recursion,唯一的区别是,最后需要将子问题的结果进行合并!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uRmHxDbk-1663382898119)(assets/image-20220913111327-zm7cajb.png)]

例题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fLkzYdoV-1663382898120)(assets/image-20220913111508-mjnplxz.png)]

算法模板

分治算法的核心是寻找子问题的解 ,解题步骤遵循「三步走」:

  1. 找到子问题并分解
  2. 解决子问题(递归)
  3. 合并子问题的解

Backtracking 回溯

  • 回溯的问题的形式:通常要求寻找满足所有 xx 条件的结果,并且问题可以使用递归实现。
  • 个人理解:一步一步先前探索,每一步尝试所有的可能,一旦发现当前不是可行解,立刻停止(知错就改)

例题

找出所有由 n 个 1 左右括号组成的有效的表达式:22. 括号生成 - 力扣(LeetCode)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9d4ZWdDg-1663382898120)(assets/image-20220913112536-bt4o7ro.png)]

具体的思路可以通过观看视频理解:【小小福讲算法】硅谷工程师十五分钟带你深入理解 Recursion (递归)算法,及其衍生出的算法(分治算法 Divide and Conquer, 回溯 Ba_哔哩哔哩_bilibili

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LUNYwIbp-1663382898120)(assets/image-20220913112812-f8z5yh4.png)]

回溯问题的模板

可以参考这篇文章:回溯法套路模板 刷通 leetcode - 知乎 (zhihu.com)

设计思路

  1. 全局变量 : 保存结果
  2. 参数设计 : 递归函数的参数,是将上一次操作的合法状态当作下一次操作的初始位置。这里的参数,我理解为两种参数:状态变量条件变量 。(1)状态变量(state)就是最后结果(result)要保存的值;(2)条件变量就是决定搜索是否完毕或者合法的值。
  3. 完成条件 : 完成条件是决定 状态变量和条件变量 在取什么值时可以判定整个搜索流程结束。搜索流程结束有两种含义: 搜索成功并保存结果 和 搜索失败并返回上一次状态。
  4. 递归过程 : 传递当前状态给下一次递归进行搜索。

套路模板

res = []    # 定义全局变量保存最终结果
state = []  # 定义状态变量保存当前状态
p,q,r       # 定义条件变量(一般条件变量就是题目直接给的参数)
def back(状态,条件1,条件2,……):
    if # 不满足合法条件(可以说是剪枝)
        return
    elif # 状态满足最终要求
        res.append(state)   # 加入结果
        return 
    # 主要递归过程,一般是带有 循环体 或者 条件体
    for # 满足执行条件
    if  # 满足执行条件
        back(状态,条件1,条件2,……)
back(状态,条件1,条件2,……)
return res

使用回溯法的明显标志

  1. 排列、组合(子集、幂集、字符全排列)。 在传值时,对于排列问题,是要删掉单个用过的元素;组合问题,是删掉前面所有的元素。
  2. 数组、字符串,给定一个特定的规则,尝试搜索迭代找到某个解。
  3. 二维数组下的 DFS 搜索(八皇后、黄金矿工、数独)

总结

  • 递归是一种非常直观的解决复杂问题的方法。(重点就在于你怎么去把这个问题抽象出简单的几步)
  • 递归分两步:Base Case+Recursion Relation

简化概念

  1. 第一、 明确递归函数的作用和参数的含义,然后坚定的相信它的作用

    1. 再次强调不要试图在脑中重演递归过程,当然你也做不到。你要做的便是:明确递归函数的作用,包括参数是什么,是否有返回值,有的话返回值是什么,然后相信它就行了。
  2. 第二、找到递归基

    1. 所谓递归基,就是递归结束的条件。比如 n == 0 的时候之类的情况。
  3. 第三、明确递归函数返回后,该做点啥

    1. 里层的递归函数返回后,需要与当前的层做一些互动,然后才能将彼此联系起来。

思考技巧

就是将问题拆分成两个部分, 即 1剩余整体,其中 剩余整体 又可以用 1剩余整体 的思想来考虑.如此思考,那么 剩余整体 完全可以用递归的方法去解决.

重中之重的点如下

联系到第一点技巧的提示,即相信剩余整体已经处理完毕之后如何与 1 的部分衔接问题.

算法选择

  • 递归遇到重复计算的情况 → 使用 memorization
  • 递归遇到子问题结果组合的情况 → 使用 divide-and-conquer
  • 递归要求返?所有满足条件的解答 → 使用 backtracking

?


  1. 获取二叉树所有双分支结点个数

    题目

    假设二叉树采用二叉链表存储结构存储,试设计一个算法,计算一棵给定二叉树的所有双分支结点个数。

    image?

    想法

    1. 按照层次遍历算法2逻辑,修改判断结点入队时逻辑即可。
    2. 前/中/后序遍历皆可

    代码实现

    非递归形式

    /**
     * 统计二叉树的所有双分支结点个数。
     *
     * @param root 根节点
     * @return 二叉树的所有双分支结点个数
     */
    public int numberOfFullTreeNode(TreeNode root) {
        int count = 0;
        Queue<TreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            while (size-- > 0) {
                TreeNode poll = queue.poll();
                assert poll != null;
                if (poll.left != null) {
                    queue.offer(poll.left);
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                }
                if (poll.left != null && poll.right != null) {
                    count++;
                }
            }
        }
        return -1;
    }
    

    递归形式

    需要重点去理解

    public int numberOfFullTreeNode(TreeNode root){
        if(root!=null){
            if(root.left!=null&&root.right!=null){
                //双分支结点
                return numberOfFullTreeNode(root.left)+numberOfFullTreeNode(root.right)+1;
            }else{
                return numberOfFullTreeNode(root.left)+numberOfFullTreeNode(root.right);
            }
        }
    }
    
    

    ? ??

  2. 层次遍历算法

    层次遍历算法

    题目

    原题:102. 二叉树的层序遍历 - 力扣(LeetCode)

    给你二叉树的根节点root,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。

    逻辑思路

    • 建立一个queue
    • 先把根节点放进去,这时候找根节点的左右两个子节点
    • 去掉根节点,此时queue里的元素就是下一层的所有节点
    • 用for循环遍历,将结果存到一个一维向量里
    • 遍历完之后再把这个一维向量存到二维向量里
    • 以此类推,可以完成层序遍历

    代码

    这个题目其实就是考察BFS求最短路径问题,🤣写这篇文章的时候还不会这招。见谅啦

    下列代码可优化

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode() {}
     *     TreeNode(int val) { this.val = val; }
     *     TreeNode(int val, TreeNode left, TreeNode right) {
     *         this.val = val;
     *         this.left = left;
     *         this.right = right;
     *     }
     * }
     */
    class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            List<List<Integer>> lists = new ArrayList<>();
            if (root == null) {
                return lists;
            }
            Queue<TreeNode> treeNodeQueue = new ArrayDeque<>();
            treeNodeQueue.add(root);
            List<TreeNode> sameStorey = new ArrayList<>();
            while (!treeNodeQueue.isEmpty()) {
                //每当队列中弹出一个元素时,就需要将弹出元素子元素(左右)进行入队操作
                List<Integer> temp = new ArrayList<>();
                while (!treeNodeQueue.isEmpty()) {
                    TreeNode poll = treeNodeQueue.poll();
                    temp.add(poll.val);
                    if (poll.left != null) {
                        sameStorey.add(poll.left);
                    }
                    if (poll.right != null) {
                        sameStorey.add(poll.right);
                    }
                }
                //将子节点加入到队列中,并清空集合
                treeNodeQueue.addAll(sameStorey);
                sameStorey.clear();
                lists.add(temp);
            }
            return lists;
        }
    }
    
    ??
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:52:38  更:2022-09-21 00:53:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 18:21:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计