题目描述
给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示
示例:
输入:{8,6,10,5,7,9,11},8
返回:9
解析:这个组装传入的子树根节点,其实就是整颗树,中序遍历{5,6,7,8,9,10,11},根节点8的下一个节点就是9,应该返回{9,10,11},后台只打印子树的下一个节点,所以只会打印9,如下图,其实都有指向左右孩子的指针,还有指向父节点的指针,下图没有画出来
解题
非专业选手(从一个小白的角度)来作答,钻研该题花了蛮长时间,希望把我的收获和大家分享一下~
1.前言
在解题之前,有几个必须明白的点:
(1)掌握关于二叉树的基础知识,才能明白做题的步骤及逻辑,了解中序遍历的遍历方式(先访问左子树,然后根节点,最后遍历右子树),最好是在大脑中一个形象推理的过程;基础知识链接:二叉树基础知识。
(2)适应牛客的网页自测IDE,一是pycharm等IDE可能不支持二叉树的操作,而且配置环境花费的时间不少;二是提前适应企业笔试;既然我们的目的是刷题和明白算法的逻辑,也就没必要纠结为什么无法在pycharm等IDE实现,而且网页自测IDE往往都把参数配置好了,直接写算法逻辑就行。
(3)本题解题的几个关键点:
pNote:也就是p结点的意思,这是本题的最重要的参数,一切的操作从它开始
pNote.right:p结点的右子结点(也有称右孩子点),也就意味着p结点存在右子树
pNote.left:p结点的左子结点,也就意味着p结点存在左子树
pNote.next:p结点的父结点,为方便理解,大家可参考标记好的下图
以上多个参数(maybe二叉树算法的表现形式)是解本题的关键
最后加上while函数:
解该题的时候才认识到while函数的强大!!
可能有点绕,但这是本文最最要的逻辑,这也是本题最大的收获
假如pNote的左结点一直存在:第一次循环判定pNote的左结点存在,pNote指代pNote的左结点,然后进行第二次循环,这次是对重新定义后的pNote(pNote.left)进行判定存在,然后依次循环,直至该结点最左的子节点。
如果这儿不是很明白,可以跳过,代码部分学习时再回头看这。
2.解题代码
解该题主要为两个步骤:
(1)如果该结点的右子树不为空,那么下个结点就是右子树里最左边的结点
因为中序遍历的逻辑是左中右,如果该结点(也就是p结点)存在右子树(也就是存在右子结点),那么遍历的下一位就到该结点的右子树上了,假如右子树没有左结点,那么答案就是它;假如有左结点,那么优先是右子树的左结点....依次循环
(2)如果该结点的右子树为空,往上找,找到的祖先结点是该祖先结点父结点的左结点!!!
第二步是往父结点方向找,因为中序遍历,该结点的父结点已经遍历过了,因此要找父结点的父结点,而且最终的父结点必须是他所在树的左结点,这个其实不难理解,只有最终的父结点是所在树的左结点,遍历才能继续下去(左中右),答案就是最终的父结点。
# -*- coding:utf-8 -*-
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None
class Solution:
def GetNext(self, pNode):
# write code here
#1.如果该结点的右子树不为空,那么下个结点就是右子树里最左边的结点
#2.如果该结点的右子树为空,往上找,找到的祖先结点是该祖先结点父结点的左结点!!!
if pNode.right:
tempnode = pNode.right
while tempnode.left: #循环判定右子树的左结点!!!妙啊
tempnode = tempnode.left
return tempnode #若该结点右子树的各个左结点不存在,返回该结点的右结点
else:
while pNode.next:
parent = pNode.next
if parent.left == pNode:
return parent
pNode = pNode.next #若非左结点,继续循环
return None
总结
大家如果有疑问都可以评论提出,有不足之处请大家批评指正,希望能多结识这方面的朋友,共同学习、共同进步。