代码训练day22|二叉树part08

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

1. 当root的val在p与q之间时,root为最近公共祖先

反证法:如果不是最近,向左/右向下遍历,都会错过p,q中的某一个

图源:代码随想录

2. 因为BST已经有序,所以此题不用遍历整颗树

如果有返回值,区分遍历边/整颗树:

图源同上

返回值不为空的时候立即返回,不需要后续的逻辑处理,所以只是搜索一条边

3. 代码习惯:

不好判断p,q大小,可以先判断两种其他情况(root<p&&root<q和root>p&&root>q),之后剩下的情况就是root的val在p和q之间

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
         if(root==null)return root;
         if(root.val>p.val&&root.val>q.val){
            TreeNode left = lowestCommonAncestor(root.left,p,q);
            if(left!=null)return left;
         }else if(root.val<p.val&&root.val<q.val){
             TreeNode right = lowestCommonAncestor(root.right,p,q);
             if(right!=null)return right;
         }
         return root;

     }
}

//简化
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
        if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
        return root;
    }
}

//迭代
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while (true) {
            if (root.val > p.val && root.val > q.val) {
                root = root.left;
            } else if (root.val < p.val && root.val < q.val) {
                root = root.right;
            } else {
                break;
            }
        }
        return root;
    }
}

701.二叉搜索树中的插入操作

二叉搜索树插入,因为BST已经有序,所以肯定不用遍历整颗树,只需要遍历边即可

返回值返回节点,可以顺便把新加入节点连上

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) // 如果当前节点为空,也就意味着val找到了合适的位置,此时创建节点直接返回。
            return new TreeNode(val);
            
        if (root.val < val){
            root.right = insertIntoBST(root.right, val); // 递归创建右子树
        }else if (root.val > val){
            root.left = insertIntoBST(root.left, val); // 递归创建左子树
        }
        return root;
    }
}

迭代法,需要双指针来记录父节点(parent),

需要单独讨论空节点

需要记录根节点,作为返回值

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) return new TreeNode(val);
        TreeNode newRoot = root;
        TreeNode pre = root;
        while (root != null) {
            pre = root;
            if (root.val > val) {
                root = root.left;
            } else if (root.val < val) {
                root = root.right;
            } 
        }
        if (pre.val > val) {
            pre.left = new TreeNode(val);
        } else {
            pre.right = new TreeNode(val);
        }

        return newRoot;
    }
}

450.删除二叉搜索树中的节点

通过递归的效果来实现删除(通过返回值)

五种情况:

这里就把二叉搜索树中删除节点遇到的情况都搞清楚。

有以下五种情况:

  • 第一种情况:没找到删除的节点,遍历到空节点直接返回了
  • 找到删除的节点
    • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
    • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
    • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
    • 第五种情况:1. 左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。2. 找到左孩子中的最大值,或者右孩子中的最小值,递归删除该最近(左子树最大/右子树最小)节点(此被删除节点肯定为2-4情况),并把其重新放到删除节点处

删除二叉树中的节点:

1. 因为没有有序性,需要遍历整颗二叉树

2. 代码中目标节点(要删除的节点)被操作了两次:

  • 第一次是和目标节点的右子树最左面节点交换(一直交换到最深处最左面节点)。
  • 第二次直接被NULL覆盖了。
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) return root;
        if (root.val == key) {
            if (root.right == null) { // 这里第二次操作目标值:最终删除的作用
                return root.left;
            }
            TreeNode cur = root.right;
            while (cur.left!=null) {
                cur = cur.left;
            }
            swap(root.val, cur.val); // 这里第一次操作目标值:交换目标值其右子树最左面节点。
        }
        root.left = deleteNode(root.left, key);
        root.right = deleteNode(root.right, key);
        return root;
    }
};

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值