题目
代码
第一种解法:
//不用先知道几个条件的简单版算法
static ArrayList<TreeLinkNode> list = new ArrayList<>();
public TreeLinkNode GetNext(TreeLinkNode pNode){
TreeLinkNode par = pNode;
while(par.next != null){
par = par.next;
}
inOrder(par);
for(int i=0;i<list.size();i++){
if(pNode == list.get(i)){
return i==list.size()-1?null:list.get(i+1);
}
}
return null;
}
void inOrder(TreeLinkNode pNode){
if(pNode!=null){
inOrder(pNode.left);
list.add(pNode);
inOrder(pNode.right);
}
}
进阶版解法:
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
//属于1
if(pNode.right!=null){
TreeLinkNode pRight = pNode.right;
while(pRight.left!=null){
pRight = pRight.left;
}
return pRight;
}
//属于2
if (pNode.next != null && pNode.next.left == pNode) {
return pNode.next;
}
//属于3
if (pNode.next != null) {
TreeLinkNode pNext = pNode.next;
while (pNext.next != null && pNext.next.right == pNext) {
pNext = pNext.next;
}
return pNext.next;
}
return null;
}
思路
- 第一种解法比较简单,就是先用par.next指向其父节点的特性,对整个二叉树进行遍历找到他们的最大父节点,然后用另外一个inOrder方法,将其以中序遍历的顺序放进list数组中,然后匹配当前pNode与list中的节点是否一致,是就直接将list的下一个节点返回,结束。
- 第二种方法,就是先手直接判断节点的3种类型,比较复杂,怎么判断的只能说要经验积累和直觉,很容易就会漏条件,非常麻烦,3个条件如下:
1.有右子树,下一结点是右子树中的最左结点,例如 B,下一结点是 H。
2.无右子树,且结点是该结点父结点的左子树,则下一结点是该结点的父结点,例如 H,下一结点是 E。
3.无右子树,且结点是该结点父结点的右子树,则我们一直沿着父结点追朔,直到找到某个结点是其父结点的左子树,如果存在这样的结点,那么这个结点的父结点就是我们要找的下一结点。例如 I,下一结点是 A;例如 G,并没有符合情况的结点,所以 G 没有下一结点
总结
这个题目比较难,关于进阶解法中各种条件的判断,一般很难想出来。建议用第一种方法遍历完二叉树,中序排好之后,再进行查找的逻辑就比较简单。
参考资料
https://blog.nowcoder.net/n/37b2e6170ffb4acaa27f67f88b1b1922?f=comment