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

【数据结构_12】二叉树(4)

一、二叉树的层序遍历

思路:可以按照先序的方式来遍历这个树,递归的时候,给递归方法,加上辅助的参数,level表示当前层数,递归过程中,根据level的值,决定当前整个节点要放到哪个list中。这个题目中,是通过二维list表示结果的,list中的[0]的元素就是根节点,如果把根节点视为第 0 层,此时的level就是和下标对应上了,如果把根节点视为第一层,就需要把level-1再作为下标。

代码段:

    public void levelOrderHelper(TreeNode root, int k,List<List<Integer>> result){if(root == null){return ;}//当前level这一层的List是否被创建出来了if(result.size() == k){result.add(new ArrayList<>());}//取出当前元素,添加到第level行中List<Integer> curRow = result.get(k);curRow.add(root.val);//递归处理左右子树levelOrderHelper(root.left,k+1,result);levelOrderHelper(root.right,k+1,result);}public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> result = new ArrayList<>();if(root == null){return result ;}levelOrderHelper(root,0,result);return  result;}

二、二叉树的最近公共祖先

从根节点到达这个指定节点,路径上经过的所有节点,都可以视为这个节点的祖先。所谓的公共祖先,意味着公共祖先子树中级同时包含了这两个节点。比如,确认了公共祖先这个节点,确实包含了p和q这两个节点,也就意味着p和q就可能出现在三个位置:

1.p/q是根节点

2.p/q存在于左子树

3.p/q存在于右子树

如果是最近的公共祖先,意味着p和q就会分布在上述三种情况的两种之中

其他的公共祖先,意味着p和q都是分布在上述三种情况的一种之中

代码的整体思路:

从根节点出发,递归地针对每个子树进行茶渣p和q的操作,对于任意一个节点,在根节点中查找p和q,在左子树中查找p和q,在右子树中查找p和q。针对上述三个范围的查找,分别使用int变量来表示查找结果.如果找到p或者q认为返回值为1;如果没找到p或者q返回值为0.

再将上述三个结果进行相加,如果

结果为0,意味着当前节点不是p和q的祖先

如果结果为1,意味着当前节点可能是p或者q的祖先

如果结果为2,意味着当前节点一定是p和q的最近公共祖先。

代码段如下:

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {private TreeNode lca = null;public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {lca = null;if(root == null){return  null;}if(root == p || root == q){return root;}//需要使用一个辅助方法进行递归,完成上述的逻辑find(root,p,q);return  lca;}public  int find(TreeNode root,TreeNode p,TreeNode q){if(root == null){return 0;}//针对根节点查找返回的0/1int mid = (root == p || root ==q )?1:0;//针对左子树查找返回的0/1int left = find(root.left,p,q);//针对右子树查找返回的 0 / 1int right = find(root.right,p,q);if(mid + right + left ==2){//说明root就是最近的公共祖先//最近公共祖先只有一个,但是find方法是递归过程中找到的//如何把这个公共祖先返回到上一个方法中去呢?lca = root;}return mid + right + left > 0 ? 1:0;}
}

这道题的一些难点:

1.理解公共祖先和最近公共祖先

2.分析出公共祖先和最近公共祖先的差异(代码来描述);三个范围中,其中的两个范围分别找到了p和q,就是最近公共祖先

3.编写代码,通过三个 0 / 1 这样的int值相加,看是否为2

4.如何方便简单地拿到返回值

三、根据前序遍历和中序遍历序列构造二叉树

关键结论:

1.先序的第一个元素,就是根节点

2.先序中,根节点左侧的就是左子树的中序;根节点右侧的就是右子树的中西

3.先序中,知道了哪些节点是左子树,哪些节点是右子树之后,此时,先序中对应的序列,也就是左右子树的先序结果

/*** 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 {//首先创建一个index来表示当前去到了preorder中的哪个元素private int index = 0;public TreeNode buildTree(int[] preorder, int[] inorder) {index =0;//创建一个方法来辅助创建树return buildTreeHelper(preorder,inorder,0, inorder.length);}public TreeNode buildTreeHelper(int[] preorder,int[] inorder, int inleft ,int inright){if(inleft >= inright){//给定的区间是空区间,意味着对应空树return  null;}if(index >= preorder.length){//说明已经遍历完了preorder这个数组return  null;}//取出index对应的元素,构造出当前的节点TreeNode root  = new TreeNode(preorder[index]);index++;//接下来要找到root在中序序列的位置int pos = findPos(inorder,inleft,inright,root.val);//再递归左子树,递归右子树root.left =buildTreeHelper(preorder,inorder,inleft,pos);root.right =buildTreeHelper(preorder,inorder,pos+1,inright);return root;}public int findPos(int[] inorder,int inleft,int inright,int val){//循环遍历for(int i=inleft;i<inright;i++){if(inorder[i]== val){return  i;}}return -1;}
}

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

http://www.xdnf.cn/news/43867.html

相关文章:

  • redis 中的 String 数据结构
  • 【Linux系统】Linux基础指令(详解Linux命令行常用指令,每一个指令都有示例演示)
  • 【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的
  • 【人工智能】推荐开源企业级OCR大模型InternVL3
  • 【后端开发】MyBatis
  • 树莓派系统中设置固定 IP
  • Oracle 23ai Vector Search 系列之6 向量相似性搜索(Similarity Search)
  • 力扣DAY60-61 | 热100 | 回溯:单词搜索、分割回文串
  • 17.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--SonarQube部署与配置
  • kotlin知识体系(六) : Flow核心概念与与操作符指南
  • opencv图像库编程
  • 软件开发过程中技术债的控制策略
  • iPhone 13P 换超容电池,一年实记的“电池循环次数-容量“柱状图
  • next.js 如何实现动态路由?
  • 【消息队列RocketMQ】一、RocketMQ入门核心概念与架构解析
  • Git拉分支技巧:从零开始创建并推送分支
  • 每天学一个 Linux 命令(28):ln
  • 产品经理学习过程
  • 深度剖析即梦 AI:开启创意无限的智能创作时代
  • springboot--web开发响应参数注解
  • Web前端:百度首页克隆 - 前端开发练习
  • 网络设备基础运维全攻略:华为/思科核心操作与巡检指南
  • 2.2 BackgroundWorker的使用介绍
  • Python实现对大批量Word文档进行批量自动化排版(15)
  • 数字系统与编码
  • 2020 年 7 月大学英语四级考试真题(组合卷)——解析版
  • 并发设计模式实战系列(4):线程池
  • RabbitMQ和Seata冲突吗?Seata与Spring中的事务管理冲突吗
  • Chromium 134 编译指南 Ubuntu篇:环境搭建与源码获取(一)
  • PyTorch基础笔记