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

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

669. 修剪二叉搜索树

与删除节点类似,但不需要讨论左/右孩子节点是否为空:

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

原因在于删除节点时,如果左右孩子均非空,需要把左孩子挂在右孩子的最左叶子节点上。但如果二叉树一定范围内的节点删除,根节点值一定在左右孩子区间中,这样范围删除不会出现左右孩子均存在的情况。(因为删除范围是趋于无限的开区间!!)所以只需要考虑挂载一边的孩子节点分支即可。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == NULL) return NULL;
        if (root->val < low) return trimBST(root->right, low, high); 
        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;
    }
};

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

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

如果根据数组构造一棵二叉树。本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间

①开辟新数组空间

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.size() == 0) return NULL;
        int midIndex = nums.size() / 2;
        TreeNode* root = new TreeNode(nums[midIndex]);
        vector<int> leftVec(nums.begin(), nums.begin() + midIndex);
        vector<int> rightVec(nums.begin() + midIndex + 1, nums.end());
        root->left = sortedArrayToBST(leftVec);
        root->right = sortedArrayToBST(rightVec);
        return root; 
    }
};

②不开辟新数组空间

因为需要记录每次分割的边界,所以需要另外开辟一个递归函数。注意分割区间是「左闭右开」。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return buildBST(nums, 0, nums.size());
    }

    TreeNode* buildBST(vector<int>& nums, int left, int right) {
        // 设置终止条件
        if (left >= right) return NULL;
        int midIndex = (left + right) / 2;
        TreeNode* root = new TreeNode(nums[midIndex]);
        root->left = buildBST(nums, left, midIndex);
        root->right = buildBST(nums, midIndex + 1, right);
        return root;
    }
};

538. 把二叉搜索树转换为累加树

538. 把二叉搜索树转换为累加树

核心在于二叉搜索树的中序遍历为递增数组

①先处理数组累加,再重新遍历来修改值

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* convertBST(TreeNode* root) {
        vector<int> vec;
        traversal(root, vec);
        for (int i = vec.size() - 2; i >= 0; i--) {
            vec[i] += vec[i + 1];
        }
        appendVal(root, vec);
        return root;
    }

    void appendVal(TreeNode* root, vector<int>& vec) {
        if (root == NULL) return;
        appendVal(root->left, vec);
        root->val = vec[0];
        vec.erase(vec.begin());
        appendVal(root->right, vec);
    }

    void traversal(TreeNode* root, vector<int>& vec) {
        if (root == NULL) return;
        traversal(root->left, vec);
        vec.push_back(root->val);
        traversal(root->right, vec);
    }
};

②遍历的同时修改值

我们知道BST的中序遍历为递增数组,但题目要求总右节点开始累加,类比的思考:其实「右中左」的遍历顺序即可获得数组的倒序数组。此时我们统一了遍历顺序和处理数组的累加顺序,保持两者的一致性。因此我们可以在遍历的同时直接进行处理。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* convertBST(TreeNode* root) {
        traversal(root);
        return root;
    }
private:
    int pre = 0;
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        // 右中左
        traversal(root->right);
        root->val += pre;
        pre = root->val;
        traversal(root->left);
    }
};
posted @ 2022-12-23 21:36  脱线森林`  阅读(572)  评论(0编辑  收藏  举报