题目
一个二叉树节点在原有的基础上添加一个parent,即任意一个节点都可以找到它的父节点,如果没有父节点则为null。给定任意一个节点,请找到它的后继节点(按照中序遍历在其后面的节点为前一个节点的后继节点)。
解法
方法一:暴力解法。因为有parent,因此可以找到最终的头节点,然后根据中序遍历,可以找到指定节点的后续,但是复杂度很高。
方法二:观察节点规律,总结规律。即如果指定节点有右子树,则其后继节点为右子树的最左的一个节点。因为中序遍历顺序就是所有的的都是 左中右,因此如果这个节点有右子树,那么它的下一个节点必定这个右子树的最左节点。如果这个节点没有右子树如何找呢?则想如果当前节点为某个根的右子树节点,则根据中序遍历规则它的没有后继节点;如果为某个根的左子树节点,则根据中序遍历规则它的后继节点是它的根节点。
沿着 parent 一直往上找,直到找到符合条件的祖先。
代码
节点定义
java
class TreeNodeH {
int val;
TreeNodeH parent;
TreeNodeH left;
TreeNodeH right;
}
java
public static TreeNodeH getTreeNodeH(TreeNodeH treeNodeH){
if (treeNodeH == null){return null;}
if (treeNodeH.right != null){ // 有右子树
TreeNodeH current = treeNodeH.right; //到达指定节点的右子树顶点
while (current.left != null){
current = current.left;
}
return current;
}else {
// 如果它的右子树为null,此时找它的作为左子树最后被打印的节点。
TreeNodeH current = treeNodeH; // 当前节点
TreeNodeH parentNode = current.parent; // 当前节点的父节点
// 判断父节点的左孩子是否是当前节点
while (parentNode != null && parentNode.left != current){
// 如果不相等,继续往上找
current = current.parent;
parentNode = parentNode.parent;
}
return parentNode;
}
}
总结
后继节点
根据中序遍历(左 -> 根 -> 右):
-
如果当前节点有右子树
- 后继就是右子树最左侧节点。
-
如果当前节点没有右子树
- 就沿着
parent一直向上寻找。 - 直到找到一个祖先,使当前节点位于该祖先的左子树中(即当前节点是父节点的左孩子) 。
- 此时这个父节点就是后继。
- 如果一直找到根都没有找到这样的祖先,则说明当前节点是中序遍历最后一个节点,没有后继。
- 就沿着
前继节点
根据中序遍历(左 -> 根 -> 右):
-
如果当前节点有左子树
- 前驱就是左子树最右侧节点。
-
如果当前节点没有左子树
- 沿着
parent一直向上寻找。 - 直到找到一个祖先,使当前节点位于该祖先的右子树中(即当前节点是父节点的右孩子) 。
- 此时这个父节点就是前驱。
- 如果一直找到根都没有找到这样的祖先,则说明当前节点是中序遍历第一个节点,没有前驱。
- 沿着
本文没有展示找到前继节点的代码,有兴趣的小伙伴可以根据总结自行尝试一下哦。