代码随想录训练营Day22 二叉树part08 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点

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

题目链接:235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)

文章链接:代码随想录 (programmercarl.com)

视频链接:二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先

 这道题与Day21做的找二叉树的最近公共祖先类似,但多出了一个条件,指定为二叉搜索树,那么我们就可以通过二叉搜索树的性质来寻找最近公共祖先了。

如果是普通二叉树,我们需要从底层开始遍历,所以要用到后续递归,但这道题由于二叉搜索树的特殊性,任何递归顺序都可以。

二叉搜索树定义:一个节点的左子树上的元素一定小于父节点的元素,右子树上的元素一定大于父节点上的元素。

所以只要我们通过前序递归,找到第一个在p和q之间的节点,假如p<q,它就代表着它的左子树上一定有一个节点p,右字数上一定有一个节点q,它就一定是最近的公共祖先,我如果往左边继续递归,会错过q,往右边递归,就会错过p。

代码如下:
 

lass Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL) return NULL;
        if((root->val>=p->val&&root->val<=q->val)||(root->val>=q->val&&root->val<=p->val)) return root;//找到在p和q之间的节点
        TreeNode*left=lowestCommonAncestor(root->left,p,q);
        TreeNode*right=lowestCommonAncestor(root->right,p,q);
        if(left!=NULL&&right!=NULL) return root;
        else if(left!=NULL&&right==NULL) return left;
        else if(left==NULL&&right!=NULL) return right;
        else return NULL;
    }
};

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

 题目链接:701. 二叉搜索树中的插入操作 - 力扣(LeetCode)

文章链接:代码随想录 (programmercarl.com)

视频链接:原来这么简单? | LeetCode:701.二叉搜索树中的插入操作

 这道题看起来花里胡哨的,其实难度并不大,不管是什么数字,我都可以在叶子节点插入。那么这道题思路就很简单了,就通过递归比较,root->val和value值的大小,如果root->val大于value,那么就递归到root的左节点,如果root->val小于value,那么久递归到root的有节点。

直到递归到root==NULL时,这就意味着已经递归到最底部了,通过创建一个新的节点插入就好了。代码如下:

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root==NULL){
            TreeNode* node=new TreeNode(val);
            return node;
        }
        if(root->val>val){
            root->left=insertIntoBST(root->left,val);
        }
        if(root->val<val){
            root->right=insertIntoBST(root->right,val);
        } 
        return root;
    }
};

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

 题目链接:450. 删除二叉搜索树中的节点 - 力扣(LeetCode)

文章链接:代码随想录 (programmercarl.com)

视频链接:调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点

 这道题其实对于算法啥的没有多少要求,主要难在对情况的考虑以及处理。这里要分五种情况。

第一种情况:二叉搜索树中根本没有这样的节点。

第二种情况:找得到节点,且是叶子节点,

第三种情况:找得到节点,有左孩子没右孩子。

第四种情况:找得到节点,没右孩子有右孩子。

第五种情况:找得到节点,左右孩子都有。

代码如下:

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)//第二种情况,叶子节点
        {
            delete root;
            return NULL;
        }
        else if(root->left!=NULL&&root->right==NULL)//第三种情况,有左孩子没右孩子
        {
            TreeNode* cur=root->left;
            delete root;
            return cur;
        }
        else if(root->left==NULL&&root->right!=NULL)//第四种情况,没左孩子有右孩子
        {
            TreeNode* cur=root->right;
            delete root;
            return cur;
        }
        else//第五种情况,左右孩子都有
        {
            TreeNode* asd=root->right;
            while(asd->left!=NULL)//通过循环找到root的右子树中最小的节点
            {
                asd=asd->left;
            }
            asd->left=root->left;
            TreeNode* cur=root->right;
            delete root;
            return cur;
        }
    }
        if(root->val>key) root->left=deleteNode(root->left,key);
        if(root->val<key) root->right=deleteNode(root->right,key);
        return root;
    }
};

还需要注意的是,C++中删除节点,还需要有delete的好习惯!

Day22 打卡成功,对二叉搜索树的进一步理解与应用,耗时2.5小时,再接再厉。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值