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

Day22

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

利用二叉搜索树的有序性,从根节点开始,第一次搜到位于这俩值之间的节点就是最近公共祖先

递归法:

class Solution {
public:
    TreeNode* travelsal(TreeNode* node,TreeNode* p,TreeNode* q){
        if(node==NULL) return NULL;
        if(node->val>p->val && node->val>q->val){
            TreeNode* left=travelsal(node->left,p,q);
            if(left!=NULL) return left; 
        }
        if(node->val<p->val && node->val<q->val){
            TreeNode* right=travelsal(node->right,p,q);
            if(right!=NULL) return right;
        }
            return node;

    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL) return NULL;
        return travelsal(root,p,q);
    }
};

迭代法:

对于迭代法,如果把这两个判断用两个while来写,会造成无法识别左右左的情况, 拐不了弯,比如第一个cur -> val 就小于 p q 的话直接就会来到第二个while,以后就不能左拐了

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        while(root){
            if(root->val>q->val && root->val > p->val){
                root=root->left;
            }
            else if(root->val < q->val && root->val<p->val){
                root=root->right;
            }
            else return root;
        }
        return NULL;
    }
};

对于需要两个while循环搞定的,试着看能不能只用一个,然后在循环内部使用判断语句。

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

递归法:

利用返回值构建父子节点关系

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root == NULL){
            TreeNode* node =new TreeNode(val);
            return node;
        }
        if(val > root->val)     root->right = insertIntoBST(root->right,val);
        if(val < root->val)     root->left =insertIntoBST(root->left,val);
        return root;
    }
};

正常递归法

class Solution {
public:
    TreeNode* parent;
    void travelsal(TreeNode* cur,int val){
        if(cur==NULL){
            TreeNode* node = new TreeNode(val);
            if(val>parent->val){
                parent->right=node;
            }
            else{
                parent->left=node;
            }
            return;
        }
        parent=cur;
        if(cur->val>val) travelsal(cur->left,val);
        if(cur->val<val) travelsal(cur->right,val);
        return;
    }
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        parent=new TreeNode(0);
        if(root==NULL){
            root=parent;
            parent->val=val;
            return root;
        }
        travelsal(root,val);
        return root;
    }
};

迭代法

个人感觉迭代的重点在于不用递归遍历整个树得到结果。

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root==NULL){
            TreeNode* node=new TreeNode(val);
            return node;
        }
        TreeNode* cur=root;
        TreeNode* parent=cur;
        while(cur!=NULL){
            parent=cur;
            if(cur->val>val){
            cur=cur->left;    
            }
            else{
            cur=cur->right;    
            }
        }
        TreeNode* node=new TreeNode(val);
        if(parent->val > val){parent->left = node;}
        else{
            parent->right = node;
        }
        return root;
    }
};

450 删除二叉搜索树中的节点

迭代法:重点是只有一个节点时的处理情况,这里又分为这个节点就是要找的key和不是要找的key两种情况。

class Solution {
public:
    TreeNode* delete1(TreeNode* cur){
        if(cur==nullptr) return nullptr;
        TreeNode* node=cur;
        if(cur->right){
            node=cur->right;
            while(node->left){
                node=node->left;
            }
            node->left=cur->left;
            return cur->right;
        }
        return cur->left;
    }
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root== nullptr){
            return root;
        }
        TreeNode* node=root;
        TreeNode* parent=nullptr;
        while(node){
            if(node->val==key) break;
            parent=node;
            if(node->val>key){
                node=node->left;
            }
            else{
                node=node->right;
            }
        }
        if(parent==nullptr) return delete1(node);
        if(parent->left&&parent->left->val==key){
            parent->left=delete1(node);
        }
        if(parent->right&&parent->right->val==key){
            parent->right=delete1(node);
        }
        return root;
    }
};

递归法

使用了上面说过的使用返回值来处理父子节点。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root==NULL){ return root;}
        if(root->val==key){
            if(!root->left&&!root->right){
                delete root;
                return nullptr;
            }
            else if(!root->left){
                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){
                    cur=cur->left;
                }
                cur->left=root->left;
                auto retnode=root->right;
                delete root;
                return retnode;
            }
        }
        if(root->val > key) root->left=deleteNode(root->left,key);
        if(root->val < key) root->right = deleteNode(root->right,key);
        return root;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值