题目:

给定一棵二叉搜索树和其中的一个节点 p ,找到该节点在树中的中序后继。如果节点没有中序后继,请返回 null 。

节点 p 的后继是值比 p.val 大的节点中键值最小的节点,即按中序遍历的顺序节点 p 的下一个节点。

剑指offer53:二叉搜索树的下一个节点_中序


输入:root = [5,3,6,2,4,null,null,1], p = 6

输出:null

解释:因为给出的节点没有中序后继,所以答案就返回 null 了。

剑指offer53:二叉搜索树的下一个节点_算法_02


输入:root = [2,1,3], p = 1

输出:2

解释:这里 1 的中序后继是 2。请注意 p 和返回值都应是 TreeNode 类型。

分析:

*第一种解法:*解决这个问题最直观的思路就是采用二叉树的中序遍历,因为中序遍历会逐一遍历二叉树的每个节点,如果二叉树有n个节点,那么这种思路的时间复杂度就是O(n),沿用中序非递归遍历模板,在栈出栈的时候判断是否是指定的节点,如果不是就接着循环,如果是则它的下一个节点就是要求的值,因为中序遍历二叉搜索树是递增顺序,所以下一个出栈的节点就是要求的值。

*第二种解法:*换一种思路,通过比较值来查找,从根节点开始,每到一个节点就比较根节点的值和节点p的值,如果当前节点的值小于或等于节点p的值,那么节点p的下一个节点应该在它的右子树,如果当前节点的值大于节点p的值,那么当前节点有可能是它的下一个节点。节点p的下一个节点是所有比它大的节点中值最小的一个,因此接下来将前往当前节点的左子树,确定是否能找到值更小但仍然大于节点p的值的节点。重复这样的比较,直到找到最终结果。

上例子

剑指offer53:二叉搜索树的下一个节点_中序遍历_03


比如要找8中序后继,上来先拿头节点8和8比较,相等则右移指针,用变量r把10先保存住,之后再左移指针找到9,r存入9,9大于8,左移为空,所以9是8的后继

比如找10的中序后继,上来拿头节点8和10比较,头节点8比10小,右移指针,找到10,10等于10,右移指针,保存11,11左移为空,因此11就是10的中序后继

代码:

import java.util.Stack;

public class InorderSuccessor {
public TreeNode inorderSuccessor1(TreeNode root,TreeNode p){
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
Boolean found = false;
while (cur !=null && !stack.isEmpty()){
while (cur!=null){
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
if (found = true){
break;
}else if (cur == p){
found = true;
}
cur = cur.right;
}
return cur;
}
public TreeNode inorderSuccessor2(TreeNode root,TreeNode p) {
TreeNode cur = root;
TreeNode result = null;
while (cur != null) {
if (cur.val > p.val){
result = cur;
cur = cur.left;
}else {
cur = cur.right;
}
}
return result;
}
}

剑指offer53:二叉搜索树的下一个节点_算法_04