给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针
传入的参数为树的某个节点,由于有指向父节点的指针存在,实际上传入的是一棵树
思路一:暴力破解法(找到整棵树的根节点,然后构造中序序列,位于该中序序列的下一个节点即为所找节点)
代码实现如下:
import java.util.ArrayList;
public class Solution {
ArrayList<TreeLinkNode> list=new ArrayList<>();
public TreeLinkNode GetNext(TreeLinkNode pNode) {
TreeLinkNode root = pNode;//**
//找出根节点
while (root.next!=null)
{
root = root.next;
}
//构造中序序列
inOrder(root);
//遍历
for(int i=0;i<list.size()-1;i++)
{
if(i!=list.size()-1&&pNode==list.get(i))
return list.get(i+1);
}
return null;
}
private void inOrder(TreeLinkNode root)
{
if(root==null)
return;
inOrder(root.left);
list.add(root);
inOrder(root.right);
}
}
值得注意的是这一句,如果该节点是列表最后一个节点,此时返回会报空指针异常
if(i!=list.size()-1&&pNode==list.get(i))
return list.get(i+1);时间复杂度 3O(N) 空间O(N)
思路二:最优解法 (举例画图)
中序遍历对于某个节点来说,其遍历顺序决定了某节点的下一节点跟其是否有左子点无关 ,与其是否有父节点、是父节点的左节点还是右节点有关
代码实现如下:
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode) {
if(pNode==null)
return null;
//存在右子树,其右子树是否有左孩子,有左孩子找最左,无左孩子就是第一个右孩子
if(pNode.right!=null)
{
pNode=pNode.right;
while(pNode.left!=null)
{
pNode=pNode.left;
}
return pNode;
}
//不存在右子树
//1、节点是其父节点的左孩子
//2、节点是其父节点的右孩子,在其父节点的路径上找到节点是其父节点的左孩子的节点,返回父节点
else if(pNode.next!=null)
{
if(pNode==pNode.next.left)
return pNode.next;
while(pNode.next!=null&&pNode!=pNode.next.left)
{
pNode=pNode.next;
}
return pNode.next;
}
//不存在右子树,也没有父节点
return null;
}
}
时间 O(N)空间O(1)
评论区更简洁的写法
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode) {
if(pNode==null)
return null;
//存在右子树,其右子树是否有左孩子,有左孩子找最左,无左孩子就是第一个右孩子
if(pNode.right!=null)
{
pNode=pNode.right;
while(pNode.left!=null)
{
pNode=pNode.left;
}
return pNode;
}
//不存在右子树
//1、节点是其父节点的左孩子
//2、节点是其父节点的右孩子,在其父节点的路径上找到节点是其父节点的左孩子的节点,返回父节点
while(pNode.next!=null)
{
if(pNode==pNode.next.left)
return pNode.next;
pNode=pNode.next;
}
//不存在右子树,也没有父节点
return null;
}
}
总结:又是一道题两个解法搞6个小时,服了
不足:
对二叉树的遍历,理解不深,代码都写不利索。题解看不懂多动笔,要不就多看几个题解,while循环的继续下去的条件,出现的bug主要是过程理解的片面,也就是思路不全