给一个二叉查找树(什么是二叉查找树),以及一个节点,求该节点的中序遍历后继,如果没有返回null
注意事项
It’s guaranteed p is one node in the given tree. (You can directly compare the memory address to find p)
样例
给出 tree = [2,1] node = 1:
2
/
1
返回 node 2.
给出 tree = [2,1,3] node = 2:
2
/ \
1 3
返回 node 3.
挑战
O(h), where h is the height of the BST.
思路
从中序遍历的特性去寻找:左-根-右。中序遍历一个结点时,下一个结点有三种情况:
- 如果当前结点有右结点,则下一个遍历的是右子树的最左结点;
- 如果当前结点无右结点,若它是父节点的左儿子,则下一遍历的是父节点;
- 如果当前结点无右结点,且它是父节点的右儿子,则所在子树遍历完了。向上寻找一个作为左儿子的祖先结点,那么下一遍历的就是该祖先结点的父节点;(一直找到根节点为止)
- 如果上面三种情况都没找到,则该节点是树的最后一个结点,无后继结点
代码
public class Solution {
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
if (root == null) {
return null;
}
// successor 记录用于记录中序遍历当前结点可能的后继结点
// 后继结点是不是 successor 需要根据当前结点是否存在右子树来确定
TreeNode successor = null;
// root 代表当前结点
// 不断查找,直到当前结点指向目标结点 p
while (root != null && root != p) {
// p 在当前结点的左子树
// 只有往左查找时 successor 才需要不断更新
if (root.val > p.val) {
successor = root;
root = root.left;
// p 在某一结点的右子树
// 向当前结点右子树查找时,successor 仍是当前结点的父结点不变
} else {
root = root.right;
}
}
// while 循环结束后 root 指向点 p
// 确定 p 的后继结点到底是 successor 还是其右子树的最左结点
// 当前结点没有右子树
if (root.right == null) {
return successor;
}
// 当前结点存在右子树,一直找到右子树最左边结点
root = root.right;
while (root.left != null) {
root = root.left;
}
return root;
}
}