第21天:删除二叉树元素没做出来。摆!

文章讨论了在二叉搜索树中查找最低公共祖先(LowestCommonAncestor)、插入新值以及删除节点的算法。对于LCA,提出了基于节点值的巧妙解决方案;插入操作通过递归实现;删除操作涉及不同情况的处理,包括叶子节点、单子节点和双子节点的情况。文章提到了作者在理解和实现这些操作时遇到的挑战以及解决方案。

第一次遇到没做出来,看答案也不理解的题。好在我觉得这题没什么价值,这样繁琐的题,在面试的时候应该只会考个思路。思路不难想。
2201的ppt都说“太长了”,想必我也不太需要掌握吧!

  1. Lowest Common Ancestor of a Binary Search Tree

算法:当遇到第一个在p,q之间(包括p,q,因为root可能是p或q本身)的数的node就是我们要找的node!剩下的根据形状调整指向就好。(很巧妙啊!)

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) return nullptr;
        if((p->val <= root->val && root->val <= q->val) || (q->val <= root->val && root->val <= p->val)) return root;
        if(root->val > max(p->val, q->val)){
            return lowestCommonAncestor(root->left, p, q);
        }else if(root->val < max(p->val, q->val)){
            return lowestCommonAncestor(root->right, p, q);
        }
        return nullptr;
    }
};
  1. Insert into a Binary Search Tree

不难,但第一次交没过。

class Solution {
private:
    void helper(TreeNode* root, int val){
        if(!root) return;
        if(root->val < val){
            if(!root->right){
                root->right = new TreeNode(val);
                return;
            }
            helper(root->right, val);
        }else{
            if(!root->left){
                root->left = new TreeNode(val);
                return;
            }
            helper(root->left, val);
        }
    }
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(!root) return new TreeNode(val);
        helper(root, val);
        return root;
    }
};

3.Delete Node in a BST (没做出来)

  1. Delete leaf node: easy!
  2. Delete node with one child: easy!
  3. Delete node with two children: find the next largest, then replace it on (if the second largest also have a right child, (since it can only have right child) attach them to the replaced node’s right node’s left child).

画了一部分时间,没做出来,放弃了。把放弃之前的代码和思路摆上去吧。

****** THIS IS INCORRECT!!!!!!!! ******
class Solution {
private:
    TreeNode* prev = nullptr;
    TreeNode* findSucc(TreeNode* root){
        while(root->left){
            root = root->left;
        }
        return root;
    }
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(!root) return root;
        if(root->val == key){
            if(!root->left && !root->right){
                delete root;
                return nullptr;
            }else if(!root->left || !root->right){
                if(!root->left){
                    prev->right = root->right;
                    delete root;
                    return prev->right;
                }else{
                    prev->left = root->left;
                    delete root;
                    return prev->left;
                }
            }else{
                TreeNode* tmp = findSucc(root->right); //second largest
                if(tmp->right){
                    root->right->left = tmp->right;
                }
                if(prev->left == root){
                    delete prev->left;
                    prev->left = tmp;
                }else{
                    delete prev->right;
                    prev->right = tmp;
                }
                return tmp;
            }
        }

        if(root->val > key) {prev = root; root->left = deleteNode(root->left, key);}
        if(root->val < key) {prev = root; root->right = deleteNode(root->right, key);}
        return root;
    }
};

具体下面这段代码为什么能过,我一点都不理解。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root;
        if (root->val == key) {
            if (root->right == nullptr) { // 这里第二次操作目标值:最终删除的作用
                return root->left;
            }
            TreeNode *cur = root->right;
            while (cur->left) {
                cur = cur->left;
            }
            swap(root->val, cur->val); // 这里第一次操作目标值:交换目标值其右子树最左面节点。
        }
        root->left = deleteNode(root->left, key);
        root->right = deleteNode(root->right, key);
        return root;
    }
};

后续:2023.2.10更新:
整理了一下心态,把这个题重写了一下,其实也没有那么难。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(!root) return root;
        if(root->val == key){
            if(!root->left && !root->right){ // leaf node
                delete root;
                return nullptr;
            }else if(!root->left && root->right){ //missing only left
                TreeNode* right = root->right;
                delete root;
                return right;
            }else if(root->left && !root->right){ //missing only right
                TreeNode* left = root->left;
                delete root;
                return left;
            }else{ //missing both
                TreeNode* tmp = root->right;
                while(tmp->left != nullptr){
                    tmp = tmp->left;
                }
                tmp->left = root->left;
                TreeNode* tmp2 = root;
                root = root->right;
                delete tmp2;
                return root;
            }
        }

        if(root->val > key) root->left = deleteNode(root->left, key);
        if(root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值