面试题 04.06. 后继者-20230225

1、题目:面试题 04.06. 后继者

设计一个算法,找出二叉搜索树中指定节点的“下一个”节点(也即中序后继)。如果指定节点没有对应的“下一个”节点,则返回null

示例1:

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

  2
 / \
1   3

输出: 2

示例2:

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

      5
     / \
    3   6
   / \
  2   4
 /   
1

输出: null

2、补充知识:

(1)先序遍历

        代码:

public void dfs(TreeNode root) {
    if (root == null) return;
    
    System.out.println(root.val);
    dfs(root.left);
    dfs(root.right);
}

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

输出:[5, 3, 2, 1, 4, 6]

(2)中序遍历

        代码:

public void dfs(TreeNode root) {
    if (root == null) return;
    
    dfs(root.left);
    System.out.println(root.val);
    dfs(root.right);
}

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

输出:[1, 2, 3, 4, 5, 6]

(3)后续遍历

        代码:

public void dfs(TreeNode root) {
    if (root == null) return;
    
    dfs(root.left);
    dfs(root.right);
    System.out.println(root.val);
}

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

输出:[1, 2, 4, 3, 6, 5]

(4)二叉搜索树的性质

        二叉搜索树又称二叉排序树,它可以是一棵空树。

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  2. 它的左右子树也分别为二叉搜索树

3、中序遍历

  • 思路:

        利用中序遍历的方法,依次遍历二叉树,找出p节点的下一个节点。

  • 代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private TreeNode p, res;

    private boolean isReturn;

    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        this.p = p;
        dfs(root);

        return res;
    }

    private void dfs(TreeNode root) {
        if (root == null) return;

        dfs(root.left);
        if (isReturn && res == null) {
            res = root;
        }
        if (p == root) {
            isReturn = true;
        }
        dfs(root.right);
    }
}

4、利用二叉搜索树的性质

  • 思路:

        利用二产搜索树的性质,左子节点的值始终小于根节点,右子节点的值始终大于根节点,中序遍历的结果就是将所有值从小到大排序。

        所以,我们只需要找到比p节点的值大的第一个节点就可以了。

  • 代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        TreeNode res = null;
        // 若p节点有右子节点的时候, 说明目标节点就在右子树的最小值的那个节点上
        if (p.right != null) {
            // 获取p节点的右子节点
            res = p.right;
            // 获取右子树的最小值的节点
            while (res.left != null) {
                res = res.left;
            }
            return res;
        }

        // 当p节点没有右子树的时候, 目标节点就不能用上面的方法查找了
        while (root != null) {
            // 当前节点的值大于p节点的值, 说明该节点可能是目标节点, 
            // 仍需继续查找是否有比当前节点的值小且大于p节点值的节点
            if (root.val > p.val) {
                // 当前节点可能是目标节点, 先将当前节点赋予res,
                // 如果后面遍历还能找到更符合要求的节点就将新节点赋予res,
                // 如果没有, 则说明当前节点就是目标节点
                res = root;
                root = root.left;
            } else { 
                // 当前节点的值大于p节点的值, 就向比当前节点值大的方向遍历
                root = root.right;
            }
        }

        // 当root为null时会返回null, 所以不需要判断
        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值