D19|BST的最近公共祖先、插入节点和删除节点

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

初始思路:

        首先其处理思路可以仿照二叉树寻找公共祖先。

        如何利用二叉搜索树特性来处理此问题,我想的是如果其中一个数值小于当前节点,另一个数值大于当前节点,那么该节点就是最近公共节点,相较于二叉搜索树可以不用遍历去寻找这个节点本身了。

 

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

        return null;

        
    }
}

递归三部曲:

1)确定输入和输出

2)确定终止条件 如果当前节点为空,return root

3)确定单层循环条件,

                如果当前节点的数值是在区间之内的就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;
    }
}

逻辑更加的清晰:

单层循环条件就是:

        如果当前根节点的数值小于要搜索的两个节点就向右搜索

         如果当前根节点的数值大于要搜索的两个节点就向左搜索

         不然就是在区间之内,返回该节点因为该节点为最近公共祖先

相比之下我对于搜索左子树还是右子树没有很明确的利用二叉搜索树的特性。


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

初始思路:

递归三部曲

(1)确认输入和输出

(2)确定终止条件,如果当前节点为null就return当前节点

(3)确定单层递归条件:

        如果该值大于root.val就应该插到root.right,如果root.right==null的话,就直接插入当作root.right,如果root.right!=null的话,就继续在root.right insertIntoBST

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

    }
}

题解复盘:

思路更加清晰

递归三部曲:(1)确定输入和输出

                        输入:当前节点、要插入的数值

                        输出:插入的节点

                      (2)确定终止条件

                                终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。

                                代码如下:

if (root == NULL) {
    TreeNode* node = new TreeNode(val);
    return node;
}

这里把添加的节点返回给上一层,就完成了父子节点的赋值操作了,详细再往下看

                     (3)确定单层递归逻辑:

此时要明确,需要遍历整棵树么?

别忘了这是搜索树,遍历整棵搜索树简直是对搜索树的侮辱。

搜索树是有方向了,可以根据插入元素的数值,决定递归方向。

代码如下:

if (root->val > val) root->left = insertIntoBST(root->left, val);
if (root->val < val) root->right = insertIntoBST(root->right, val);
return root;

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

初始思路&&题解复盘:

明确五种情况:

1)没有找到要删除的节点

2)找到了要删除的节点:如果该节点为叶子节点,左节点为空右节点为空,直接删除该节点,return null

3)找到了要删除的节点:该节点左为空右不为空返回右节点

4)找到了要删除的节点:该节点左不为空右为空返回左节点

5)找到了要删除的节点,该节点左不为空右也不为空,

                                          左子树接在右子树的左叶子上,返回右子树的根节点当作新根

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root==null){return null;}
        if(root.val==key){
            if(root.left==null&&root.right==null){return null;}
            if(root.left==null&&root.right!=null){return root.right;}
            if(root.left!=null&&root.right==null){return root.left;}
            if(root.left!=null&&root.right!=null){
                TreeNode cur = root.right;
                while(cur.left!=null){
                    cur = cur.left;
                }
                cur.left = root.left;
                return root.right;
            }
        }
        if(root.val<key){root.right=deleteNode(root.right,key);}
        if(root.val>key){root.left = deleteNode(root.left,key);}
        return root;
    }
}

插入操作和删除节点都利用了这个思想:

有返回值的话,可以利用返回值完成新加入的节点与其父节点的赋值操作

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值