二叉搜索树中的中序后继

137 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情

一、题目

LeetCode 二叉搜索树中的中序后继

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

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

示例 1:

输入:root = [2,1,3], p = 1
输出:2
解释:这里 1 的中序后继是 2。请注意 p 和返回值都应是 TreeNode 类型。

示例 2:

输入:root = [5,3,6,2,4,null,null,1], p = 6
输出:null
解释:因为给出的节点没有中序后继,所以答案就返回 null 了。

提示:

树中节点的数目在范围 [1, 104] 内。
-105 <= Node.val <= 105
树中各节点的值均保证唯一。

二、题解

给定有一颗二叉搜索树,二叉搜索树就是如果左子树不为空的话,那么左子树上所有节点值都小于根节点值;如果右子树不为空的话,那么右子树的所有节点值都大于根节点值。要找到某个指定节点的中序遍历后续节点。

方法一

可以直接按题目要求先对二叉搜索树进行中序遍历,在中序遍历之后获取的遍历结果找到指定的节点p,如果节点p之后还有后续节点就返回这个后续节点,否则返回null。具体的通过dfs深度优先搜索遍历给定的二叉搜索树节点,按中序遍历的顺序将节点加入结果数组中,遍历结果数组寻找目标节点p,如果目标节点p不是最后一个节点,那么就返回节点p的后一个节点即可。

方法二

可以利用二叉搜索树的特性,即节点值的大小顺序,遍历二叉搜索树的节点,如果当前节点值大于目标节点p的值,而节点p的中序后继节点是大于节点p的,所以这个节点p的中序后继节点就可能是在左子树中,则需要到左子树中寻找,并且先保存好这个比目标节点p大的当前节点,当遍历结束时这个节点就是节点p的中序后继节点;如果当前节点值小于目标节点p的值,那么就需要到右子树中继续寻找,直到最后遍历结束。

三、代码

方法一 Java代码

class Solution {
    List<TreeNode> list = new ArrayList<>();
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        dfs(root);
        int idx = list.indexOf(p);
        if (idx == list.size() - 1) {
            return null;
        }
        return list.get(idx + 1);
    }

    private void dfs(TreeNode root) {
        if (root == null) {
            return;
        }
        dfs(root.left);
        list.add(root);
        dfs(root.right);
    }
}

时间复杂度:O(n),需要遍历一次二叉树节点。

空间复杂度:O(n),存储遍历结果的数组以及递归消耗栈空间。


方法二 Java代码

class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        TreeNode node = null;
        while (root != null) {
            if (root.val > p.val) {
                node = root;
                root = root.left;
            } else {
                root = root.right;
            }
        }
        return node;
    }
}

时间复杂度:O(n),需要遍历下二叉树节点。

空间复杂度:O(1),只需使用常数的空间。