自学内容网 自学内容网

代码随想录算法【Day20】

Day20

二叉搜索树

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

理解只要当前节点的值在p和q节点的值的中间,那这个值就是最近的公共祖先,绝对不是次近的,这个题就好做了。

递归法

二叉搜索树本身是有序的,所以不涉及到前中后序的遍历

class Solution {
private:
    TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q){
        //先判断当前节点为空的情况
        if(cur == NULL) return NULL;
        //当前节点的值大于p和q节点的值,则遍历当前节点的左子树
        if(cur->val > p->val && cur->val > q->val){
            TreeNode* left = traversal(cur->left, p, q);
            return left;
        }
        当前节点的值小于p和q节点的值,则遍历当前节点的右子树
        if(cur->val < p->val && cur->val < q->val){
            TreeNode* right = traversal(cur->right, p, q);
            return right;
        }
        return cur;
    }
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return traversal(root, p, q);
    }
};

迭代法

使用while循环进行迭代

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;
    }
};
701.二叉搜索树中的插入操作

虽然有多种插入方式,导致插入后的结构不是唯一的,但是无论插入什么值,我们都可以在叶子结点找到相应的插入位置

递归法1

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

递归法2

迭代法

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

难点在于删除之后,要怎样去调整树的结构

添加节点的情况,不用去改二叉搜索树的结构,一定找到一个合适的叶子结点的位置

删除节点的情况,要分五种情况去分析:

①没找到要删的节点

②删除的节点,其左为空,右为空,即叶子结点

③删除的结点,其左不空,右为空,直接让父节点指向其子节点

④删除的结点,其左为空,右不空,直接让父节点指向其子节点

⑤删除的结点,其左不空,右不空,假如我们删除节点7,如下:

我们固定我们的删除方法,即让右孩子当新的父节点,并让左孩子连接到右孩子最左侧节点上

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 -> right == nullptr){
                TreeNode *retNode = root -> left;
                delete root;
                return retNode;
            }
            // ④删除的结点,其左为空,右不空,直接让父节点指向其子节点
            else if(root -> left == nullptr){
                TreeNode *retNode = root -> right;
                delete root;
                return retNode;
            }
            // ⑤删除的结点,其左不空,右不空
            else{
                // 先找到右孩子最左侧的节点
                TreeNode *cur = root -> right;
                while(cur -> left != nullptr) cur = cur -> left;
                cur -> left = root -> left;
                TreeNode* tmp = root;
                root = root -> right;
                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;
    }
};

代码虽然很多,只要慢慢分析是不难的,不能有畏难情绪。


原文地址:https://blog.csdn.net/qq_59414507/article/details/145119607

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!