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

Leetcode 235. 二叉搜索树的最近公共祖先
思路分析:
二叉搜索树是二叉树的特例,因此本题也可采用236. 二叉树的最近公共祖先相同的解法,leetcode上也能通过测试。只是没利用二叉搜索树中序遍历有序的特征,不是最优解。
如果root->val比p->val和q->val都大,则说明最近公共祖先一定在root的左子树中。反之,root->val比p->val和q->val都小,则说明最近公共祖先一定在root的左子树中。如果上述2条件都不满足,则返回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);
        } else if (root->val < p->val && root->val < q->val) {
            return lowestCommonAncestor(root->right, p, q);
        } else return root;
    }
};

Leetcode 701.二叉搜索树中的插入操作
思路分析:
题意虽然说可能存在多种有效的插入方式,实际上并需要给出所有可能结果,只需给出一种答案就行。根据二叉搜索树中序遍历有序的特征,可以根据root->val与val的关系确定递归顺序,而且顺序是唯一确定的。只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点。
此解法递归是带有返回值的,可以实现遍历到空节点,完成插入操作后,直接用返回值(root->left和root->right)接住返回值,直接完成新二叉搜索树的构建。如果不使用带返回值的递归,则需要专门定义parent节点,插入也需要操作parent.

代码实现:

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (!root) {
            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;
    }
};

Leetcode 450.删除二叉搜索树中的节点
思路分析:
删除值为key的节点也要遍历二叉搜索树,可以根据root->val与key的关系决定遍历顺序,同时用root->left或root->right接住递归返回值。单层逻辑里,如果root->left为空,则用非空的root->right节点替换root节点,如果root->right为空,则用非空的root->left节点替换root节点。同时为防止因指针指向变化导致的内存泄漏问题,需要delete root。
如果单层逻辑里root->left和root->right都不为空,则找到右子树中最小的节点作为当前节点的替换节点,将其值赋给当前节点,然后在右子树中递归删除这个最小节点。见方法1. 当然,也可以找到左子树中最大的节点作为当前节点的替换节点,将其值赋给当前节点,然后在左子树中递归删除这个最大节点。见方法2.

代码实现:
找到值为key的节点,并从右子树中移动最小值替代该节点

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) return nullptr;
        
        if (root->val > key) {
            root->left = deleteNode(root->left, key);
        } else if (root->val < key) {
            root->right = deleteNode(root->right, key);
        } else {
            if (!root->left) {
                TreeNode* temp = root->right;
                delete root;
                return temp;
            } else if (!root->right) {
                TreeNode* temp = root->left;
                delete root;
                return temp;
            }
            
            TreeNode* temp = root->right;
            while (temp->left) {
                temp = temp->left;
            }
            root->val = temp->val;
            root->right = deleteNode(root->right, temp->val);
        }
        return root;
    }
};

找到值为key的节点,并从左子树中移动最大值替代该节点

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) return nullptr;
        
        if (root->val > key) {
            root->left = deleteNode(root->left, key);
        } else if (root->val < key) {
            root->right = deleteNode(root->right, key);
        } else {
            if (!root->left || !root->right) {
                TreeNode* temp = root->left ? root->left : root->right;
                delete root;
                return temp;
            }
            
            TreeNode* temp = root->left;
            while (temp->right) {
                temp = temp->right;
            }
            root->val = temp->val;
            root->left = deleteNode(root->left, temp->val);
        }
        return root;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值