代码随想录算法训练营第21天|235. 二叉搜索树的最近公共祖先 |701.二叉搜索树中的插入操作 |450.删除二叉搜索树中的节点

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

相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。本题迭代和递归方法都简单,因为有序。 

题目链接/文章讲解:代码随想录

视频讲解:二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先_哔哩哔哩_bilibili

算法思路:利用二叉搜索树的特性:左<根<右。 遍历二叉搜索树,如果当前节点比P,Q的节点都大,则P,Q的公共祖先向该节点左子树寻找,反之,如果当前节点比P,Q的节点都小,则P,Q的公共祖先向该节点右子树寻找,当找到第一个在P、Q大小之间的节点,即为最小公共祖先。

应用场景:求二叉搜索树最近公共祖先,因为 有序。

递归法

递归三部曲如下:

  • 确定递归函数返回值以及参数

参数就是当前节点,以及两个结点 p、q。

返回值是要返回最近公共祖先,所以是TreeNode * 。

代码如下:

TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q)
  • 确定终止条件

遇到空返回就可以了,代码如下:

if (cur == NULL) return cur;
  • 确定单层递归的逻辑

在遍历二叉搜索树的时候就是寻找区间[p->val, q->val](注意这里是左闭右闭

那么如果 cur->val 大于 p->val,同时 cur->val 大于q->val,那么就应该向左遍历(说明目标区间在左子树上)。需要注意的是此时不知道p和q谁大,所以两个都要判断

整体代码:

class Solution {
private:
    TreeNode* traversal(TreeNode* cur,TreeNode* p,TreeNode* q) {
        if (cur == NULL) return cur;
                                        //  中
        if (cur->val > p->val && cur->val > q->val) { // 左
            TreeNode* left = traversal(cur->left, p, q);
            if (left != NULL) {
                return left;
            }
        } 

        if (cur->val < p->val && cur->val < q->val) {
            TreeNode* right = traversal(cur->right, p, q);
            if (right != NULL) {
                return right;
            }
        } 
        return cur;                              
    }
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return traversal(root, p, q);
    }
};

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

本题比想象中的简单,大家可以先自己想一想应该怎么做,然后看视频讲解,就发现 本题为什么比较简单了。

学完后的感想:二叉搜索树插入节点的思路真的简单,因为二叉树一有序起来,思路真的很好想,且插入节点不用考虑改变树的结构。

算法思路:插入的任意新节点往叶子节点插就行了。 任意节点在叶子处都能找到位置,因为只要满足二叉搜索树:左<根<右 的特性就行。

应用场景:二叉搜索树,插入节点

递归法

递归三部曲:

  • 确定递归函数参数以及返回值

参数就是根节点指针,以及要插入元素,这里递归函数要不要有返回值呢?

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

递归函数的返回类型为节点类型TreeNode * 。

代码如下:

TreeNode* insertIntoBST(TreeNode* root, int val)
  • 确定终止条件

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

代码如下:

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;

下一层将加入节点返回,本层用root->left或者root->right将其接住

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.删除二叉搜索树中的节点 

相对于 插入操作,本题就有难度了,涉及到改树的结构 

题目链接/文章讲解:代码随想录

视频讲解:调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点_哔哩哔哩_bilibili

学完后的想法:基于我目前对二叉树的掌握情况,本题偏难,不在我一刷掌握范围内,只大概听了一下解题思路 。(多提一句,普通二叉树节点的删除比二叉搜索树还难)

解题思路挺好想的,无非就五种情况:文字看不懂可直接看视频讲解,视频讲的很清楚

1.没有找到要删除的节点,

2.删的是叶子节点,

3.删的节点左子树为空右子树不为空(此时父节点直接略过删除节点指向右子树节点),

4.删的节点左子树不为空右子树为空(此时父节点直接略过删除节点指向左子树节点),

5.左右子树均不为空(此时父节点直接略过删除节点指向右子树节点,其左子树节点接入右子树节点的左子树下)

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值