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

递归思路讲解

最近刷到了树这一模块的算法题,树相关的算法题几乎都是用递归来实现的,但递归的思路却有点抽象,每次遇到递归,都是通过递归来深度或广度地遍历树,但对于递归遍历树的遍历路线,却有点抽象难懂,不知道遍历的路线是怎么样的,也对于返回的路线有点懵懂。

虽然知道是用递归,也知道递归可以一层一层从上到下地遍历,大体上的一个遍历路线是明白的,但是真要将递归一层层拆解分析的话,我还是有点不知所措的,所以今天研究了一小时,彻底将递归的一层层遍历拆解分析透彻了。

记录一下拆解分析的过程,以防之后又忘了,方便回顾。

 

拿上面这棵树来分析,遍历的代码是:

private void dfs(TreeNode root, int depth) {
        if (root == null) {
            return;
        }
        // 先访问 当前节点,再递归地访问 右子树 和 左子树。
        if (depth == res.size()) {   // 如果当前节点所在深度还没有出现在res里,说明在该深度下当前节点是第一个被访问的节点,因此将当前节点加入res中。
            res.add(root.val);
        }
        depth++;
        dfs(root.right, depth);
        dfs(root.left, depth);
    }

 这里将 dfs(root,0)一层层地拆解分析:

1.首先传入树的根节点root,和depth = 0

2.进入方法先判断root 是否为null, 为null 则return,这里也是后面递归的终止条件,当遍历到叶子结点下一节点时返回上一层。

3.进入到dfs(root.right,depth)递归环节,root.right = 1,depth = 0

(1)先判断root.right 是否为null,这里不为null,root.right = 3 ,depth = 1

(2)继续向下递归,先判断root.right.right 是否为null,这里不为null,root.right.right = 6 ,depth = 2

(3)继续向下递归,先判断root.right.right.right是否为null,这里为null,则return到上一层,跳到root.right.right = 6 ,depth = 2这一层

(4)在root.right.right = 6 ,depth = 2这一层,dfs(root.right.right.right,depth)已结束,执行下一句dfs(root.right.right.left,depth),进入方法后判断是否为null,不为null,root.right.right.left = 8,depth = 3

(5)在root.right.right.left = 8,depth = 3这一层,分别递归右子树和左子树,都为null,则返回root.right.right.left = 8,depth = 3这一层;同时root.right.right = 6 ,depth = 2这一层已经全部结束,返回到了root.right = 3 ,depth = 1这一层

(6)在root.right = 3 ,depth = 1这一层,右子树已经遍历完毕,开始遍历左子树dfs(root.right.right,depth),左子树为null,则root.right = 3 ,depth = 1这一层的左右子树也已经遍历完毕,所以回到了root.right = 1,depth = 0

4.此时dfs(root.right,depth)这句代码已经全部执行完毕,到了dfs(root.left,depth)这句话的执行,root.left = 2,depth = 1,然后像第3步一样开始从右子树--->左子树地递归

 

思路其实就像是套娃一样,一个大的盒子里装了两个小的套娃,这两个套娃里分别装着一层层的套娃,我们要先结束一个大的套娃,再结束另一个大的套娃。

 如果文字看的比较抽象,可以参考这个视频辅助理解:

递归算法很难?小s带你10分钟完成手把手推导,用递归求二叉树深度


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

相关文章:

  • Python →爬虫实践
  • OCR识别铁路电子客票
  • WebGIS三维地图框架--Cesium
  • three.js 杂记
  • NoSQL数据库与关系型数据库的主要区别
  • 重构代码之内联临时变量
  • C/C++开发神器CLion全新发布v2023.1——新软件包管理解决方案
  • python语法入门到面向过程编程(七)
  • QML动画分组(Grouped Animations)
  • 6. 计算机网络
  • synchronized用法加锁原理
  • 深入浅出C++ ——异常
  • Ubuntu 安装和配置 Samba服务开启共享文件夹
  • 【光伏预报/太阳能预报】上海道宁与Solargi为您提供开发地理数据库模拟工具和网络服务
  • 关于项目移植过程中,如何在不修改java源程序的情况下,如何适应新环境下的mysql
  • web小游戏开发:华容道(完)
  • 功能齐全的 ESP32 智能手表,具有多个表盘、心率传感器硬件设计
  • Bizcharts 3.0 到 4.0 升级部分问题记录
  • 现代CMake高级教程 - 第 5 章:链接第三方库
  • spring1:核心和设计思想
  • Vue3中双向数据绑定与Pinia实践+JS数据引用的循环修改问题
  • 【Docker_windows】安装Docker桌面版
  • 2023哪款蓝牙耳机性价比高?200左右高性价比蓝牙耳机推荐
  • windows11 安装多个mysql8
  • 2019临沂中考数学解析
  • 2023年华中杯C题计算结果