算法学习|二叉树 LeetCode 235. 二叉搜索树的最近公共祖先 、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

一、二叉搜索树的最近公共祖先

思路

如果从上往下遍历,发现某结点在p和q的中间(结点的左子树有p/q,右子树有q/p),那么此结点一定是p和q的最近公共祖先,因为不管从结点向左左或者向右遍历,都会错过成为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);   
    }
};
//迭代法
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
     while(root){
         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 return root;
     }
     return NULL;
    }
};

二、二叉搜索树的插入操作

思路

新插入的结点在对应的叶子结点插入
当遍历结点为空时,就找到了插入结点的位置,如果当前遍历结点的值大于val,插入结点到当前节点的左子树中,如果当前遍历结点的值小于val,插入节点到当前节点的右子树中。

代码实现

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;
    }
};

三、删除二叉搜索树中的结点

思路

先找到删除结点,然后删除结点
1.没找到要删除的结点
2.找到了要删除的结点:
叶子结点(左为空,右为空):直接删除结点,返回NULL为根节点
左不空右为空:删除结点,左孩子补位,返回左孩子为根节点
左为空右不空:删除结点,右孩子补位,返回右孩子为根节点
左不空右不为空:将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

代码实现

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root == nullptr) return root;
        if(root->val == key) {
            if(root->left == nullptr && root->right == nullptr) {
                delete root;
                return nullptr;
            }
            else if(root->left == nullptr) { // 左为空,右不为空
                auto retNode = root->right;
                delete root;
                return retNode;
            }
            else if(root->right == nullptr) { // 右为空,左不为空
                auto retNode = root->left;
                delete root;
                return retNode;
            }
            else{ //左右孩子都不为空
                TreeNode* cur= root->right;
                while(cur->left != nullptr) {
                    cur = cur->left;
                }
                cur->left = root->left; //要删除的结点的左子树放在cur的左孩子的位置
                TreeNode* tmp = root;
                root = root->right; // root的右孩子作为新的root
                delete tmp;
                return root;
            }
        }//把新的结点返回给上一层
        if(root->val > key) root->left = deleteNode(root->left, key);
        if(root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值