JZ8 二叉树的下一个结点

描述

给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示



示例:

输入:{8,6,10,5,7,9,11},8

返回:9

解析:这个组装传入的子树根节点,其实就是整颗树,中序遍历{5,6,7,8,9,10,11},根节点8的下一个节点就是9,应该返回{9,10,11},后台只打印子树的下一个节点,所以只会打印9,如下图,其实都有指向左右孩子的指针,还有指向父节点的指针,下图没有画出来

分析

初拿到这道题,很明显看出是一个二叉树的中序遍历就可以解决的问题,但是仔细看了题目之后,发现,题目会给两个参数,而这两个参数组装成的是一个二叉树节点(可以是其中树的任意节点),这样的话,如果使用普通的遍历方法直接做,就会有问题,需要多一步遍历这个节点的next找到整棵树的根节点,之后使用dfs进行中序遍历得到结果。

代码

      /**
* JZ8 二叉树的下一个结点
* @param pNode
* @return
*/
public TreeLinkNode GetNext(TreeLinkNode pNode) {
//提出题目中要求对比的值
Integer value = pNode.val;
//通过不断的寻找next找到整棵树的根节点
while (pNode.next != null) {
pNode = pNode.next;
}
//结果队列
Queue<TreeLinkNode> queue = new LinkedList<>();
//dfs遍历使用的栈,储存没有遍历过的节点用
Stack<PosNode> treeStack = new Stack<>();
//根节点
PosNode rootNode = new PosNode(pNode);
//根节点加入栈
treeStack.push(rootNode);
//如果所有节点都已经遍历过就跳出循环
while (treeStack.size() > 0) {
//中序遍历,先遍历左子树
if (treeStack.peek().node.left != null && treeStack.peek().visitLeft == false) {
PosNode posNode = new PosNode(treeStack.peek().node.left);
//证明左子树访问过
treeStack.peek().visitLeft = true;
treeStack.push(posNode);
}else {
//把节点值值存储在结果队列中
queue.offer(treeStack.peek().node);
//证明左子树访问过
treeStack.peek().visitLeft = true;
//开始遍历右子树
if (treeStack.peek().node.right != null && treeStack.peek().isVisitRight == false) {
PosNode posNode = new PosNode(treeStack.peek().node.right);
treeStack.peek().isVisitRight = true;
treeStack.push(posNode);
}else {
//如果右子树也遍历过或者为空的话
treeStack.peek().isVisitRight = true;
//通过出栈寻找左右子树都没有遍历过的节点
while (treeStack.size() != 0 && treeStack.peek().isVisitRight == true && treeStack.peek().visitLeft == true)
treeStack.pop();
}
}
} //存储的中序遍历结果进行值的比较找出结果
while (queue.size() != 0) {
if (queue.peek().val != value) {
queue.poll();
}else {
queue.poll();
return queue.peek();
}
} //找不到的话返回空值
return null;
} /**
* 保存节点以及记录节点的左右子树是否访问过的表质量
*/
class PosNode{
TreeLinkNode node;
boolean visitLeft = false;
boolean isVisitRight = false; PosNode(TreeLinkNode node) {
this.node = node;
}
}

总结

需要熟练使用代码来遍历二叉树,本人的方法使用内存占用较高,后续可以去除结果队列,直接在遍历中使用标志量记录结果返回。

剑指offer:JZ8 二叉树的下一个结点的更多相关文章

  1. 【剑指Offer】二叉树的下一个结点 解题报告(Python)

    [剑指Offer]二叉树的下一个结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...

  2. 【Java】 剑指offer(7) 二叉树的下一个结点

    本文参考自<剑指offer>一书,代码采用Java语言.  更多:<剑指Offer>Java实现合集 题目 给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?  ...

  3. Go语言实现:【剑指offer】二叉树的下一个结点

    该题目来源于牛客网<剑指offer>专题. 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回. 注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. Go语 ...

  4. 剑指Offer 57. 二叉树的下一个结点 (二叉树)

    题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 题目地址 https://www.nowcoder.c ...

  5. [剑指Offer] 57.二叉树的下一个结点

    题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. /* struct TreeLinkNode { in ...

  6. 剑指offer——06二叉树的下一个节点

    题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针.   题目的意思是,在一颗二叉树的中序遍历中,给出其中一 ...

  7. 剑指offer57:二叉树的下一个结点

    1 题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 2 思路和方法 中序遍历,下一个结点有两种情况 a ...

  8. [剑指Offer]8-二叉树的下一个节点

    链接 https://www.nowcoder.com/practice/9023a0c988684a53960365b889ceaf5e?tpId=13&tqId=11210&tPa ...

  9. 【剑指offer】面试题 8. 二叉树的下一个结点

    面试题 8. 二叉树的下一个结点 NowCoder 题目描述 给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指 ...

随机推荐

  1. 手动编译部署LNMP环境(CentOS7.5+Nginx-1.18.0+MySQL-5.7.30+PHP-7.4.14)

    在平时运维工作中,经常需要用到LNMP应用框架.LNMP环境是指在Linux系统下,由Nginx + MySQL + PHP组成的网站服务器架构. 可参考前面的文章: 如何在CentOS 7上搭建LA ...

  2. throws声明异常中断式处理异常

    1.throws 编译期异常,一直往上抛最后是JVM处理(打印并中断程序) 2.声明多个或者直接声明父类

  3. 前缀树及其Java实现

    前缀树 基础知识 Trie树.又称之为单词查找树或者键树,是一种树形结构.应用于统计和排序大量的字符串.常被搜索引擎系统用于文本词频统计.它的优点:能够最大限度的减少无谓的字符串比较,查询效率比哈希表 ...

  4. 痞子衡嵌入式:原来i.MXRT1xxx系列里也暗藏了Product ID寄存器

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx系列里暗藏的Product ID寄存器. MCU 厂商在定义一个产品系列时,通常是会预先规划产品发展路线的(即会有一 ...

  5. 在excel中,应用公式到多行

    当一个单元格中输入公式后, 选中单元格 然后将鼠标放到右下角的控制手柄处,当鼠标变成"黑十字"标志 双击鼠标左键 即可

  6. crontab 语法和最快速的学习

    1.Cron 时间表语法 # ┌───────────── 分钟 (0 - 59) # │ ┌───────────── 小时 (0 - 23) # │ │ ┌───────────── 月的某天 ( ...

  7. 多线程run()方法是不能够被直接调用的

    操作系统线程的五种状态: 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于"可运行 ...

  8. POJ1426——Find The Multiple (简单搜索+取余)

    题意: 给一个数n,让你找出一个只有1,0,组成的十进制数,要求是找到的数可以被n整除. 用DFS是搜索 当前位数字 (除最高位固定为1),因为每一位都只有0或1两种选择,换而言之是一个双入口BFS. ...

  9. 如何获取PHP命令行参数

    使用 PHP 开发的同学多少都会接触过 CLI 命令行.经常会有一些定时任务或者一些脚本直接使用命令行处理会更加的方便,有些时候我们会需要像网页的 GET . POST 一样为这些命令行脚本提供参数. ...

  10. Linux系列(23) - echo

    作用:打印 格式:echo [选项] [输出内容] 选项:-e :支持反斜线控制的字符转换 前置条件:必须加选项-e才能使用 控制字符 作用 \a 输出警告音 \b 退格符,也就是向左删除键 \n 换 ...