且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

LintCode领扣 题解丨 美团面试真题:二叉查找树的中序后继

更新时间:2021-08-28 03:58:40

给定一个二叉查找树(什么是二叉查找树),以及一个节点,求该节点在中序遍历的后继,如果没有则返回null

保证p是给定二叉树中的一个节点。(您可以直接通过内存地址找到p)
在线评测地址:
https://www.lintcode.com/problem/inorder-successor-in-bst/?utm_source=sc-tianchi-sz0820

样例 1:

输入: {1,#,2}, node with value 1
输出: 2
解释:
1
\

2

样例 2:

输入: {2,1,3}, node with value 1
输出: 2
解释:

2

/ \
1 3
【题解】

首先要确定中序遍历的后继:

如果该节点有右子节点, 那么后继是其右子节点的子树中最左端的节点
如果该节点没有右子节点, 那么后继是离它最近的祖先, 该节点在这个祖先的左子树内.
使用循环实现:

查找该节点, 并在该过程中维护上述性质的祖先节点
查找到后, 如果该节点有右子节点, 则后继在其右子树内; 否则后继就是维护的那个祖先节点
使用递归实现:

如果根节点小于或等于要查找的节点, 直接进入右子树递归
如果根节点大于要查找的节点, 则暂存左子树递归查找的结果, 如果是 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;
    }
}

更多题解参见 :https://www.jiuzhang.com/solution/inorder-successor-in-bst/?utm_source=sc-tianchi-sz0820