给定一个二叉查找树(什么是二叉查找树),以及一个节点,求该节点在中序遍历的后继,如果没有则返回null
- 保证p是给定二叉树中的一个节点。(您可以直接通过内存地址找到p)
样例 1:
输出: 2
解释:
1
\
2
样例 2:
输入: {2,1,3}, node with value 1
输出: 2
解释:
2
/ \
1 3
免费福利:点此处免费领取LintCode7天VIP,选择一周时间,输入兑换码9C06EB
【题解】
首先要确定中序遍历的后继:
- 如果该节点有右子节点, 那么后继是其右子节点的子树中最左端的节点
- 如果该节点没有右子节点, 那么后继是离它最近的祖先, 该节点在这个祖先的左子树内.
使用循环实现: - 查找该节点, 并在该过程中维护上述性质的祖先节点
- 查找到后, 如果该节点有右子节点, 则后继在其右子树内; 否则后继就是维护的那个祖先节点
使用递归实现: - 如果根节点小于或等于要查找的节点, 直接进入右子树递归
- 如果根节点大于要查找的节点, 则暂存左子树递归查找的结果, 如果是 null, 则直接返回当前根节点; 反之返回左子树递归查找的结果.
- 在递归实现中, 暂存左子树递归查找的结果就相当于循环实现中维护的祖先节点.
另外在《九章算法面试高频题冲刺班》有讲到更优化的解法,具体代码如下
public class Solution {
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
TreeNode successor = null;
while (root != null && root.val != p.val) {
if (root.val > p.val) {
successor = root;
root = root.left;
} else {
root = root.right;
}
}
if (root == null) {
return null;
}
if (root.right == null) {
return successor;
}
root = root.right;
while (root.left != null) {
root = root.left;
}
return root;
}
}
// version:高频题班
public class Solution {
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
if (root == null || p == null) {
return null;
}
if (root.val <= p.val) {
return inorderSuccessor(root.right, p);
} else {
TreeNode left = inorderSuccessor(root.left, p);
return (left != null) ? left : root;
}
}