一套模板搞定二叉树算法题--二叉树算法讲解002

这篇具有很好参考价值的文章主要介绍了一套模板搞定二叉树算法题--二叉树算法讲解002。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、二叉树的递归

递归:

2、二叉树遍历之DFS深度优先遍历

2.1、遍历的概念

每个节点 都要恰好被访问一次,本质上是二叉树的线性化

一个树形的结构,线性化为一个数组之类的"串"的结构。

2.2、DFS深度优先遍历

示例二叉树原型图:

2.2.1、前序遍历

前序遍历执行顺序:
根节点--对左子树做前序遍历--对右子树做前序遍历

总的顺序:根节点--左子树--右子树
左子树中:根-左-右
根节点
右子树中:根-左-右

对A的左子树做前序遍历

A的左子树的根节点是B

对B的左子树做前序遍历

对B的右子树做前序遍历

对E的左子树前序遍历

至此,A的左子树做完了前序遍历:

然后,对A的右子树做前序遍历:

至此,二叉树的前序遍历完成。

我们会发现,整个深度优先的遍历过程都是 递归的。

2.2.2、中序遍历

中序遍历执行顺序:
对左子树做中序遍历--根节点--对右子树做中序遍历

总的顺序:左子树--根节点--右子树
左子树中:左--根-右
根节点
右子树中:左-根-右

2.2.3、后序遍历

后序遍历执行顺序:
对左子树做后续遍历--对右子树做后续遍历--根节点

总的顺序:左子树--右子树--根节点
左子树中:左--右-根
根节点
右子树中:左-右-根

2.2.4、总结

所谓前序、中序、后序的区别。
就是根在前、根在中、还是根在后?
左、右的顺序都是不变的,从左到右。

3、DFS深度优先遍历之代码实现

4、二叉树三种深度遍历

4.1 leetcode 144 前序遍历

4.2 leetcode 94 中序遍历

4.3 leetcode 145 后序遍历

5、从深度遍历序列还原二叉树--经典题

5.1、leetcode105 从前序与中序遍历序列构造二叉树

题目:

题意:

题解思路:

前序:
前序的根:

前序的根确定为3

再根据中序确定左右子树

根据前序和中序的遍历规则确定20为右子树的根:

总结步骤
1、根据提供的前序数组的第一个元素,确定二叉树的根节点
2、找到根节点后,在中序数组中,根据根节点切割左右
左边为二叉树左子树内容,右边为二叉树右子树内容
3、再将中序数组切割的左右,返回给前序,在重复步骤1、2做递归操作

再来一个示例树讲解步骤,强调递归的体现:

找到根节点3和左子树、右子树

递归右子树:

右子树的根节点20和左子树、右子树

核心思路:
其实是个子数组的过程,即把2个大数组(前序和中序数组)不断拆成更小的数组的过程
1个大数组的拆分过程,可以使用2个指针来做拆分这件事
实现过程中重要的3个指针:
pre_start、in_start、in_end、同时也会用到代表根节点的idx

3个指针的含义:

图解:

递归:
下一次递归左子树时:
pre_start 是 pre_start+1
in_start还是in_start不变
in_end是idx-1

下一次递归右子树时:
pre_start 是 pre_start + (idx - in_start)+ 1
in_start是idx+1
in_end还是in_end

这样我们就可以实现递归了。

可以再看一个类似的示例图:

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

# 对于任何一颗子树:
# 根节点一定在前序遍历数组的第一个位置
# 可以找到根节点在中序遍历数组中的位置,其左边为左子树,右边为右子树
# 然后对左子树和右子树进行递归操作
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int], ) -> Optional[TreeNode]:
        # 构建一个哈希表,key为节点的值,value为节点在中序遍历数组中的索引
        # 方便直接通过节点值取到下标
        dic = {val: i for i, val in enumerate(inorder)}
        n = len(inorder)
        # 递归入口
        return self.help(dic, preorder, inorder, 0, 0, n-1)

def help(self, dic, preorder, inorder, pre_start, in_start, in_end):
    # 递归终止条件:若遍历区间不存在,返回空节点
    if in_start > in_en
    
    
    
        return None

    # 获得当前区间的根节点的值node_val,为preorder[pre_start]
    node_val = preorder[pre_start]
    # 获得该节点在中序遍历数组中的位置
    idx_node = dic[node_val]

    # 构建节点node
    node = TreeNode(node_val)
    
    
    # 进行递归

    # pre_start
    # ↓
    # 3 | 9  5 | 20  15  7
    #     ↑       ↑             左子树和右子树的pre_start

    # in_start        in_end
    # ↓               ↓
    # 9  5 | 3 | 15  20  7
    #        ↑
    #        idx_node

    # 9  5 | 3 | 15  20  7
    # ↑  ↑                      左子树的in_start和in_end
    #             ↑      ↑      右子树的in_start和in_end
    
    node.left = self.help(dic, preorder, inorder, pre_start + 1, in_start, idx_node - 1)
    node.right = self.help(dic, preorder, inorder, pre_start + (idx_node - in_start) + 1, idx_node + 1, in_end)

    # 将该节点回传
    return node

注:
代码中的 {val: i for i, val in enumerate(inorder)} 表示我们将 inorder 列表中的每个元素作为字典的键,将其索引作为对应的值。

例如,如果 inorder 是 [4, 2, 7, 5, 1, 3, 6] ,那么生成的字典 dic 将是 {4: 0, 2: 1, 7: 2, 5: 3, 1: 4, 3: 5, 6: 6} 。

5.2、leetcode106 从中序与后序遍历序列构造二叉树

题目:

题解:

5.3、2023C-二叉树的广度优先遍历

题目:

题意和思路:
先根据中序和后序遍历构造二叉树,再进行二叉树的层序遍历
相当于leetcode106和leetcode102这2题的组合。

6、二叉搜索树

6.1、二叉搜索树的概念和性质

6.2、二叉搜索树的查找

查找n次,每次有2个分支中的1个;
即为: \(2^n = k\)
\(n = log_2^k\)

每次查找只进入2个分支中的1个,所以时间复杂度为O(log(n))
可以理解为一种特殊的二分查找,和二分查找的时间复杂度是一样的。
或者说二叉搜索树是二分查找在树形结构上的体现

6.2.1、二叉搜索树查找代码模板

6.2.2、二叉搜索树查找--leetcode 700

题目和题意:

题解:
注意思考,递归子问题为什么要return?

如果对上述的return的写法不熟悉,可以改为如下使用成员变量的写法:
初始化成员变量 self.ans = None

6.3、二叉搜索树的增加

6.3.1、二叉搜索树的增加 -- leetcode 701

题目和题意:

题解:

6.3.2、二叉搜索树的增加 -- 2023C 计算三叉搜索树的高度

题目和题意

题解:
这题其中关键部分的解法(树的插入部分)和 leetcode 701几乎一样。

6.3.3、二叉搜索树的增加 -- leetcode 98 验证二叉搜索树

题目:

解题思路:
用二叉搜索树的性质
①、先中序遍历出树
②、再判断树的值是否从小到大排列的。

其中步骤1就是leetcode94 中序遍历二叉树。
题解:

注:
步骤1中序遍历二叉树可以这样实现

也可以这样回传列表的方式实现 实现的方式多种多样

7、总结


注:
文中截图源自大佬: 闭着眼睛学数理化 课程内容文章来源地址https://www.toymoban.com/news/detail-786681.html

到了这里,关于一套模板搞定二叉树算法题--二叉树算法讲解002的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 二叉树的非递归遍历算法

    二叉树的遍历是指访问二叉树的每个结点,且每个结点仅被访问一次。二叉树的遍历可按二叉树的构成以及访问结点的顺序分为4种方式:先序遍历、中序遍历、后序遍历和层次遍历。请至少给出其中一种遍历方式的非递归算法的思路和代码,并举例演示算法的执行过程。 算

    2023年04月24日
    浏览(32)
  • 【数据结构】树与二叉树(十三):递归复制二叉树(算法CopyTree)

      二叉树是一种常见的树状数据结构,它由结点的有限集合组成。一个二叉树要么是 空集 ,被称为 空二叉树 ,要么由一个根结点和两棵不相交的子树组成,分别称为 左子树 和 右子树 。每个结点最多有两个子结点,分别称为左子结点和右子结点。 引理5.1:二叉树中层数

    2024年02月01日
    浏览(30)
  • 二叉树的遍历的递归与非递归算法

    按照一定规律对二叉树的 每个结点进行访问且 仅访问一次 ; 这里的访问:可以是计算二叉树中的结点数据,打印该结点的信息,也可以是对结点进行的任何其它操作! 为什么需要遍历二叉树? 从过遍历可以得到访问结点的顺序序列,遍历操作就是将二叉树的结点按一定的

    2024年04月15日
    浏览(27)
  • 计算二叉树深度算法(递归、非递归)入门详解

    一、引言 二叉树在应用时,经常需要知道二叉树的深度。二叉树的深度就是二叉树的层数,即从树根算起,到最底下一层的层数是多少,即二叉树中结点的最大层次值。 本文给出了计算二叉树深度的算法,包括递归算法和非递归算法。 二、计算二叉树的基本方法 如下图所示

    2024年01月17日
    浏览(26)
  • 二叉树遍历之中序遍历算法(非递归、递归)入门详解

    一、引言 二叉树的遍历常见的方法有先序遍历、中序遍历、后序遍历和层次遍历等,本文给出了C语言版本的中序遍历二叉树的非递归算法和递归算法。 中序遍历的原理很简单,也就是把树根的访问放在中间。访问结点的次序是:“左—根—右”,也就是首先访问左子树,之

    2024年02月06日
    浏览(29)
  • 二叉树遍历的非递归算法

    非递归的算法主要采用的是循环出栈入栈来实现对二叉树的遍历,下面是过程分析 以下列二叉树为例:(图片来自懒猫老师《数据结构》课程相关内容) 1.前序遍历 前序遍历的顺序为:根结点-左子树-右子树 基本过程: (1) 访问根结点 ,将根结点入栈 (2)循环逐个访问

    2024年02月02日
    浏览(31)
  • 【数据结构】二叉树的遍历递归算法详解

    我们来写一个函数 BuyNode(x)函数 用于创建二叉树结点。 用动态开辟函数 malloc 函数进行动态开辟,并强制转换为 BTNode 型,用变量 node 来去管理开辟的空间。 我们初始化结点,其 val 即为传入的参数x,左右指针 left 和 right 都设为NULL。 我们在主函数中创建上面这样一颗二叉树

    2024年01月20日
    浏览(33)
  • 【算法第十一天7.25】二叉树前、中、后递归、非递归遍历

    树的结构 ================================================ 链接 :力扣94-二叉树中序遍历 递归 思路 1、 确定返回值和方法参数 :需要集合来存放树各节点的值,最后打印出来,所以需要一个list集合作为参数,不断迭代;除此之外不需要有返回值 2、 确定终止条件 :当前节点为空时,

    2024年02月15日
    浏览(34)
  • LeetCode算法递归类—二叉树中的最大路径和

    目录 124. 二叉树中的最大路径和 - 力扣(LeetCode) 题解: 代码: 运行结果: 二叉树中的  路径  被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中  至多出现一次  。该路径  至少包含一个  节点,且不一定经过根节点。 路径和

    2024年02月12日
    浏览(28)
  • 二叉树中序遍历非递归算法C语言实现

    // //  Inordertraverse.c //  二叉树链式存储 // //  Created by 丘** on 2021/7/28. // #include \\\"Inordertraverse.h\\\" #include stdbool.h #includestdlib.h typedef   struct StackNode {     int data;     struct StackNode* next;      }StackNode; typedef struct BiTNode {     int data;     struct BiTNode* lchild,* rchild;           }BiTnode

    2024年02月02日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包