找二叉树中给定元素的的左孩子结点_【数据结构与算法】二叉树经典考题

文字长度: ★★★☆☆

阅读难度: ★★☆☆☆

原创程度: ★★★★★


前言

树是一种数据结构,二叉树是一种特殊的树,二叉搜索树是一种特殊的二叉树。本文总结了二叉树/二叉搜索树中我认为最经典的一些题目,比较复杂的配了图来帮助理解。

目录-----加【】的是题目

  • 树基本概念
    • 深度
    • 高度
    • 叶子
  • 二叉树
    • 遍历序列
      • 【前序遍历】iterative解法
      • 【中序遍历】iterative解法
      • 【后序遍历】iterative解法
      • 【给中序+前序,还原二叉树】(1) recursive解法; (2) iterative解法
      • 【给二叉树,求层次遍历序列】BFS解法
    • 平衡树
      • 【判断是否是平衡树】
    • 后继结点/前驱结点
      • 【求后继结点】(1) 知道parent; (2)不知道parent
  • 二叉搜索树 (BST)
    • 查询
      • 【BST中查询某值】
      • 【BST的最大/小值】
    • 结点变换
      • 【移植子树】
      • 【BST中插入一个结点】
      • 【BST中删除一个结点】(1) iterative解法; (2) recursive解法
    • 构造
      • 【从有序数组中构建平衡的BST】(1) recursive解法; (2) iterative解法

1. 所有树都有的属性

【深度】对于某个结点而言,其深度(depth)就是从树的根结点到该结点的路径长度,即经过的结点数量(包括根结点但不包括自己),根结点的深度是0。孩子的深度=自己的深度+1。

相关考题: 求树中某个结点的深度
  • 思路: DFS和BFS都可以

【高度】: 树中任意结点的深度的最大值,也即树中任意叶子的深度的最大值。

相关考题: 求树的高度
  • 思路: DFS和BFS都可以

【层】: 所有拥有深度y的结点组成的集合称作树的level-y,根结点在level-0

【叶子】: 没有孩子结点的结点

2. 二叉树特有的属性名词

【遍历序列】 分为前序遍历序列,中序遍历序列,后序遍历序列,层次遍历序列。这部分典型的知识点包括: 写出

  • 前序遍历 (Preorder Traversal) 不用递归的写法
vector
  • 中序遍历 (Inorder Traversal) 不用递归的写法
vector
  • 后序遍历 (Postorder Traversal) 不用递归的写法
vector
1. 给定前序+中序,还原二叉树(或者求后序,本质没差别)
  • Recursive解法: 解题的核心要点是: preorder的第一个一定是根inorder的根结点左边是左子树,右边是右子树
    • 时间复杂度: O(N^2)(对每个结点都要搜索,共n个结点)
    • 空间复杂度: 除了递归栈,使用了O(1) 辅助空间
TreeNode
  • Iterative解法: 这个解法比较优雅
    • 时间复杂度: O(N)
    • 空间复杂度: O(N)
    • 将前序遍历的结点依次入栈,同时后一个结点作为前一个结点的左孩子,不断叠加。
    • 如果前序遍历当前结点等于中序遍历的当前结点,出栈结点直到和中序遍历的结点不相等。并且同时设置flag为true,来标记做了一次pop操作。
    • 重复上述过程直到前序遍历的栈为空。
    • 核心要点
      • 只有preorder序列入栈操作时会在树中插入新结点
      • flag为true时,插入新结点到上一个结点的右孩子位置,并且reset flag.

f6b32bb1c14ad17ee22f9bfa966af78c.png
TreeNode
2. 给定后序+中序,还原二叉树
  • 和前序+中序一样,只不过postorder的最后一个结点一定是根
给定二叉树,求层次遍历序列
  • 经典的BFS解法
vector

【平衡树】任意节点的子树的高度差都小于等于1

相关考题: 判断一个给定的二叉树是否是平衡树
bool 

【后继结点】(successor) 在给定二叉搜索树中,求某结点的中序遍历的后继结点

相关考题: 给定一个二叉搜索树,求某结点的中序遍历的后继结点的值
  • 如果该结点有右孩子,那么就返回右孩子的最小结点( 时间复杂度O(logN) );否则返中序遍历中在自己后面并且最接近自己的祖先(找到结点的最近(层数差距最小)的祖先,使得该结点所在的子树是该祖先的左孩子) 。中序遍历中在自己后面并且最接近自己的祖先的求法分2种情况
    • 第一种:二叉搜索树的结点有指向parent的指针,那么找到该祖先的方式是从该结点出发,向上搜索直到找到满足条件的祖先。
      • 时间复杂度: O(logN)
/**
  • 第二种:二叉搜索树的结点没有指向parent的指针,那么找到该祖先的方式是从root出发,用一个指针curr去找该结点p,另一个指针succ用来记录当前值最小的祖先,如果遇到一个大于p的值的祖先,succ指针就指向之前的curr,curr指向它的左孩子。
    • 时间复杂度: O(N)

14ffd0d4daaac2640ad1259da3241b9f.png
第二种情况示意图
TreeNode

【前驱结点】: 和“后继结点”相应,做对称操作即可

3. 二叉搜索树的基本操作

【查询】给定二叉搜索树中是否存在值为x的结点。查询是二叉搜索树最基本的操作。

TreeNode
  • 变种题: 给定二叉搜索树中是否存在值为x的结点,如果存在,返回该结点到根的距离,如果不存在返回-1
TreeNode

最大/小值查询】: 求给定二叉搜索树的最大/小值

TreeNode

移植】将某个树v移植到树root的结点u处

TreeNode

【插入】在一个二叉搜索树中插入一个结点。注意,被插入的结点必然是一个“叶子”结点

8dffeac8a3ce91472a45def5d48bc1f8.png
TreeNode 

【删除】: 在一个二叉搜索树中删除一个值为x的结点,如果该值不存在,则返回原来的树

删除一个结点比插入结点复杂很多,因为被删除的结点可能不是“叶子”结点。我们具体分为3种情况讨论:

  • 如果被删除的结点只有左子树,那么就用p的左孩子移植到p的位置
  • 如果被删除的结点只有右子树,那么就用p的右孩子移植到p的位置
  • 如果被删除的结点有左右2个子树,那么需要找到右子树中最小的结点x,将它放到p的位置。由于x肯定没有左子树(否则不会是子树上最小的结点),但是可能有右子树。所以移动x到p之前,需要先把x从子树上删除。

63680376faf470c15a6760657f4d7aaf.png
// iterative 思路
  • 另外还有一个recursive的思路:
    • 如果当前结点就是需要被删除的结点
      • 如果没有右孩子,就是把当前结点删除
      • 如果有右孩子,将右子树上的最小结点和当前结点的值交换,再去删除右子树上的该值
    • 如果当前结点的值大于需要被删除的值,那么被删除的值在左子树上
    • 如果当前结点的值小于需要被删除的值,那么被删除的值在右子树上
// recursive 思路

构造】从一个有序数组,构建平衡的二叉搜索树

  • recursive思路: 很直观,不需要多说
    • 时间复杂度: O(N),显然每个结点对应调用了一次buildBST函数
    • 空间复杂度: 即递归栈深度,O(logN)
TreeNode
  • iterative: 由于从有序数组构建BST是一个深度优先遍历的问题,因此iterative的解法用栈来解决。
    • 时间复杂度: O(N),显然是遍历了一遍数组
    • 空间复杂度: 即压栈最深的深度,也即树的高度,O(logN)
TreeNode
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值