代码随想录Day23|669.修建二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

修剪二叉搜索树

669. 修剪二叉搜索树 - 力扣(LeetCode)

在给定二叉搜索树的根节点root的同时,给定最小边界low和最大边界high,通过修剪二叉搜索树,使得所有节点值在[low,high]中。

逐个删除

我的想法,范围外的节点全部删除,参考昨日二叉搜索树节点的删除操作,但由于每次都需要遍历,导致时间复杂度为O(n)。代码如下:

class Solution {
public:
TreeNode* find_parent(TreeNode* root, int key) {
        if (root == nullptr || (root->left == nullptr && root->right == nullptr)) {
            return nullptr; // 如果当前节点为空或为叶节点,返回nullptr
        }
        if (root->left != nullptr && root->left->val == key) {
            return root; // 如果左子节点的值等于key,返回当前节点作为父节点
        }
        if (root->right != nullptr && root->right->val == key) {
            return root; // 如果右子节点的值等于key,返回当前节点作为父节点
        }
        if (key < root->val) {
            return find_parent(root->left, key); // 如果key小于当前节点的值,递归地在左子树中查找
        } else {
            return find_parent(root->right, key); // 如果key大于或等于当前节点的值,递归地在右子树中查找
        }
    }
 
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return nullptr;
 
        if (root->val == key) {
            // 要删除的节点是根节点
            if (root->left == nullptr) return root->right; // 只有右子树
            if (root->right == nullptr) return root->left; // 只有左子树
            // 有两个子节点,找到右子树的最小节点
            TreeNode* minNode = getMin(root->right);
            root->val = minNode->val; // 将右子树的最小节点的值赋给当前节点
            root->right = deleteNode(root->right, minNode->val); // 删除右子树中的最小节点
        } else if (key < root->val) {
            root->left = deleteNode(root->left, key); // 在左子树中递归删除
        } else {
            root->right = deleteNode(root->right, key); // 在右子树中递归删除
        }
        return root;
    }
 
    TreeNode* getMin(TreeNode* node) {
        while (node->left != nullptr) 
            node = node->left;
        return node;
    }
   TreeNode* trimBST(TreeNode* root, int low, int high) {
    if (root == nullptr) {
        return nullptr;
    }
    
    // 否则,递归修剪左右子树
    root->left = trimBST(root->left, low, high);
    root->right = trimBST(root->right, low, high);
    // 如果当前节点的值不在[low, high]范围内,则删除该节点
    if (root->val < low || root->val > high) {
        TreeNode* newRoot = deleteNode(root, root->val); // 删除当前节点,并获取新的根节点
        return trimBST(newRoot, low, high); // 递归修剪新的树
    }
    return root;
    }
};

注意这里是用后序遍历,而非之前的前序遍历,后序遍历使得每次都从底部开始删,能避免前序导致的部分节点无法删除。

递归法

注意此处当某节点左孩子不符合时范围时,并不能直接返回nullptr,而应将左孩子的右孩子return,同理,当某节点右孩子不符合范围时,需return右孩子的左孩子。

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == nullptr) {
            return nullptr;
        }
        // 删除不在范围内的节点
        if (root->val < low) {
            return trimBST(root->right, low, high); // 递归修剪右子树
        } else if (root->val > high) {
            return trimBST(root->left, low, high); // 递归修剪左子树
        }
        // 递归修剪左右子树
        root->left = trimBST(root->left, low, high);
        root->right = trimBST(root->right, low, high);
        return root;
    }
};

算法的时间复杂度和空间复杂度为O(logn)

释放空间写法,会报错

TreeNode* trimBST(TreeNode* root, int low, int high) {
    if (root == nullptr) {
        return nullptr;
    }
    // 如果节点值不在[low, high]范围内,删除节点并释放空间
    if (root->val < low) {
        TreeNode* rightSubtree = trimBST(root->right, low, high);
        delete root; // 释放当前节点的内存
        return rightSubtree; // 返回修剪后的右子树
    } else if (root->val > high) {
        TreeNode* leftSubtree = trimBST(root->left, low, high);
        delete root; // 释放当前节点的内存
        return leftSubtree; // 返回修剪后的左子树
    }
    // 递归修剪左右子树
    root->left = trimBST(root->left, low, high);
    root->right = trimBST(root->right, low, high);
    return root;
}

将有序数组转换为二叉搜索树

108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)

递归法

先写终止方法,当数组为空时,return nullptr,找寻中位设置为根,将数组分为左右两部分,并带入遍历左右节点。最后返回。

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums, int start, int end) {
        if(start > end)
            return nullptr;
        int mid = start + (end - start) / 2; // 防止溢出
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = sortedArrayToBST(nums, start, mid - 1);
        root->right = sortedArrayToBST(nums, mid + 1, end);
        return root;
    }

    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return sortedArrayToBST(nums, 0, nums.size() - 1);
    }
};

算法的时间复杂度为O(n),空间复杂度为O(log(n))。

把二叉搜索树转换为累加数

538. 把二叉搜索树转换为累加树 - 力扣(LeetCode)

很巧妙的思路,反转中序遍历,右中左的顺序,累加数即累加每个节点的值即可。

class Solution {
public:
    int sum = 0;
    TreeNode* convertBST(TreeNode* root) {
        if(root == nullptr){
            return nullptr;
        }
        convertBST(root->right);
        sum += root->val;
        root->val = sum;
        convertBST(root->left);
        return root;
    }
};

算法的时间复杂度为O(n),空间复杂度为O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值