[刷题记录Day22]Leetcode二叉树

番茄随想 / 2023-08-27 / 原文

No.1

题目

二叉搜索树的最近公共祖先

思路

  • 递归法
  • BST特性如何利用?在BST中,公共祖先一定在p、q数值范围的中间
  • 利用BST特性定向搜索
  • 注意递归遍历一条边和遍历整棵树的写法不同

递归分析

  1. 返回值:节点,参数:当前节点,p,q
  2. 终止逻辑:发现当前节点为空,则直接返回当前节点;
    1. 为什么不用判断p和q与root值的情况?因为不需要遍历到p和q实际的值,通过范围的剪枝就可以找到p、q的方向
  3. 单层递归分析:p、q都大于当前节点,则向右子树搜索;p、q都小于当前节点,则向左子树搜索;当前节点在p、q中间,则直接返回当前节点;

代码

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {  
    if (root == null)  
        return root;  
  
    if (root.val > p.val && root.val > q.val) {  
        TreeNode leftTree = lowestCommonAncestor(root.left, p, q);  
        // 有结果直接返回,即这条边遍历结束,无需继续搜索  
        if (leftTree != null)  
            return leftTree; // return 终止当前递归函数  
    }  
  
    if (root.val < p.val && root.val < q.val) {  
        TreeNode rightTree = lowestCommonAncestor(root.right, p, q);  
        if (rightTree != null)  
            return rightTree;  
    }  
  
    // 为什么排除上门2种情况后的root一定是最近公共祖先?很重要  
    // 只剩下root val在p和q之间的情况  
    return root;  
}

No.2

题目

二叉搜索树中的插入操作

思路

  • BST,沿着一条路径递归

递归分析

  1. 返回值:节点,记录插入位置,参数:当前节点,和待插入的值
  2. 终止逻辑:终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回
  3. 单层递归逻辑:待插入值比当前值小,left指向递归返回;待插入值比当前值大,right指向递归返回;

代码

有返回值,用下一层递归返回值赋值给本层

public TreeNode insertIntoBST(TreeNode root, int val) {  
    if (root == null) {  
        return new TreeNode(val);  
    }  
  
    if (root.val < val)  
        root.right = insertIntoBST(root.right, val);  
    if (root.val > val)  
        root.left = insertIntoBST(root.left, val);  
  
    return root;  
}

无返回值

private TreeNode pre = null;  
  
private void insertHelper(TreeNode node, int val) {  
    if (node == null) {  
        TreeNode temp = new TreeNode(val);  
        if (pre.val < temp.val)  
            pre.right = temp;  
        if (pre.val > temp.val)  
            pre.left = temp;  
        return;  
    }  
  
    if (node.val < val) {  
        pre = node;  
        insertHelper(node.right, val);  
    }  
  
    if (node.val > val) {  
        pre = node;  
        insertHelper(node.left, val);  
    }  
}  
  
public TreeNode insertIntoBST(TreeNode root, int val) {  
    // 提前滤除直接给空树的情况  
    if (root == null)  
        return new TreeNode(val);  
  
    // 至少1个节点,递归开始后,pre一定不为null  
    insertHelper(root, val);  
    return root;  
}

No.3

题目

删除二叉搜索树中的节点

思路

  • 递归

递归分析

  1. 返回值:删除节点后的子树根,参数:节点,要删除的值
  2. 终止条件:遇到空节点,说明没找到要删除的节点
  3. 单层递归过程:五种情况
    1. 第一种情况:没找到删除的节点,遍历到空节点直接返回了
    2. 找到删除的节点,第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
    3. 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
    4. 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
    5. 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

代码