代码随想录训练营第二十二天| 第六章 二叉树 part8

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

解题思路

        二叉搜索树满足左子树的所有值小于中间结点的值,右子树的所有值大于中间结点的值。所以如果中间结点是p、q的公共祖先,中间结点的数值一定是在这个区间内的。从上往下递归遍历,第一次遇到符合条件的结点值,就是我们所要找的最近公共祖先。

        由于不知道p 、q结点值的大小,所以可以先进行判断,p对应val值较小的结点。

代码解析

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        
        if(p->val > q->val)
        {
            swap(p, q);
        }

        // return p;
        if(root->val > p->val && root->val < q->val)
        {
            return root;
        }

        if(root->val < p->val)
        root =  lowestCommonAncestor(root->right, p, q);

        if(root->val > q->val)
        root = lowestCommonAncestor(root->left, p, q);


        return root;

        
    }
};

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

解题思路

        本题的关键是遇到空结点就插入结点就可以。

递归三部曲:

  1. 确定函数参数及返回值: 参数是根结点指针以及要插入的元素,返回值是新加入的结点;
  2. 确定终止条件: 当遍历的结点为null时,就是需要插入结点的位置,并把插入的结点返回;
  3. 单层递归的逻辑: 由于是二叉搜索树,不需要遍历整颗树。根据插入元素的数值决定递归的方向
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 接住。

代码解析

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root == nullptr)
        return new TreeNode(val);
        // 寻找指定位置

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

        return root;


    }
};

LeetCode 235. 删除二叉搜索树的结点

解题思路

        相比上一道题目,本题复杂在于删除一个结点可能要调整二叉树的结构。遍历过程中首先要找到这个结点,然后根据这个结点的左、右孩子情况进行讨论。

  1. 结点为空,说明没找到,返回空结点;
  2. 该结点是叶子结点,直接返回null 给其父结点;
  3. 该结点的左孩子不为空,右孩子为空,删除结点,左孩子补位,返回左孩子给其父结点;
  4. 该结点的左孩子为空,右孩子不为空,删除结点,右孩子补位,返回右孩子给其父结点;
  5. 该结点的左、右孩子都不为空,将删除结点的左子树 放到删除结点的右子树的左边面结点的左孩子上,返回删除结点的右孩子;

代码解析

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {

        if(root == nullptr)
        return nullptr;

        if(root->val ==key)
        {

            if(root->left !=nullptr && root->right == nullptr)
            {
                return root->left;
            }
            else if(root->left == nullptr && root->right!=nullptr)
            {
                return root->right;
            }

            else if(root->left !=nullptr && root->right !=nullptr)
            {
                TreeNode * cur = root->right;
                while(cur->left !=nullptr)
                {
                    cur = cur->left;
                }

                cur->left = root->left;

                return root->right;

            }

            else
            {
                return nullptr;
            }
        }


        if(key < root->val) 
        root->left = deleteNode(root->left, key);

        if(key > root->val)
        root->right = deleteNode(root->right, key);


        return root;

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值