welcome to my blog
剑指offer面试题8(java版):二叉树的下一个节点
题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针
思路
- 要弄清楚中序遍历
- 具体思路见注释
复杂度
- 时间复杂度: 和数的深度有关
- 空间复杂度: 没有分配额外的空间, O(1)
第三次做, 按照当前节点有无右子树分类两类进行讨论; 中序遍历是左根右, 如有当前节点没有右子树, 那么他的下一个节点有两种可能, 一种是null, 另一种是某个节点; 结果是某个节点时说明当前节点在某个节点的左子树中; 赋值名称要有意义, curr指向pNode, father指向curr.next
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
if(pNode==null)
return null;
TreeLinkNode curr;
//有右子树
if(pNode.right!=null){
curr = pNode.right;
while(curr.left!=null)
curr = curr.left;
return curr;
}
//没有右子树; 需要向上找到这样一个节点, 使得pNode在该节点的左子树中
else{
//curr指向当前节点pNode
curr = pNode;
///father是curr的父节点
TreeLinkNode father = pNode.next;
//如果pNode是根节点, 就没有下一个节点了
if(father==null)
return null;
//
while(father!=null && father.right==curr){
curr = father;
father = father.next;
}
//here, father==null || father.left==curr
return father;
}
}
}
第二次做, 根据当前节点有无右子树分为两大类情况进行讨论; 最麻烦的情况是当前节点没有右子树, 如果当前节点是父节点的左孩子则返回当前节点, 否则继续向上遍历,细节见代码
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
if(pNode==null)
return null;
if(pNode.right != null){
TreeLinkNode curr = pNode.right;
while(curr.left!=null)
curr = curr.left;
return curr;
}
else{//没有右子树
//当前节点是根节点
if(pNode.next==null)
return null;
TreeLinkNode curr = pNode, p = curr.next;
//当前节点的父节点是根节点
if(p.next==null){
if(p.left==curr)
return p;
return null;
}
while(p!=null){
if(p.left==curr)
return p;
curr = p;
p = p.next;
}
return null;
}
}
}
/*
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
// 健壮性判断
if(pNode == null)
return null;
// 开始正常执行
/*
首先明确当前节点的下一个节点由其右子树或者祖先节点决定, 跟它的左子树没有关系
1.当前节点有右子树,则下一个节点是右子树中最左子节点
2.当前节点没有右子树
2.1当前节点有父节点
2.1.1当前节点是其父节点的左子节点, 则下一个节点是当前节点的父节点
2.1.2当前节点是其父节点的右子节点, 当前节点的父节点记作p
2.1.2.1向上遍历p的父节点,直到找到这样一个节点, 该节点是其父节点的左子节点
2.1.2.2向上遍历p的父节点,如果遇到null,则说明当前节点是最后一个节点,没有下一个节点
2.2当前节点没有父节点
说明当前节点是最后一个节点, 没有下一个节点了, 返回null
可以看出,上面总共有2大类情况
*/
//1.
if(pNode.right != null){
TreeLinkNode curr = pNode.right;
while(curr.left != null){
curr = curr.left;
}
return curr;
}
//2.1
if(pNode.next != null){
TreeLinkNode curr = pNode.next;
//2.1.1
if(pNode == curr.left)
return curr;
//2.1.2 (包括了2.1.2.1和2.1.2.2)
TreeLinkNode father = curr.next;
while(father != null && curr == father.right ){
curr = father;
father = curr.next; //如果father是null了, 则while判断中的father.right就会报错,所以需要扩充while中的条件
}
return father;
}
//2.2
return null;
}
}