(23/60)修剪二叉搜索树、将有序数组转化为二叉搜索树、把二叉搜索树转换为累加树

修剪二叉搜索树

leetcode:669. 修剪二叉搜索树

递归法

思路

和删除搜索树节点类似,递归向上返回子树。

  1. 碰到NULL节点,向上抛NULL;

  2. 如果值小于左边界,那么当前根节点和左子树都要剪掉,返回递归右子树的结果;

    如果值大于右边界,那么当前根节点和右子树都要剪掉,返回递归左子树的结果;

  3. root->left接收左子树递归结果;

    root->right接收右子树递归结果;

  4. 返回root

复杂度分析

时间复杂度:O(logN)。

空间复杂度:O(logN)/O(N)。

注意点

代码实现

(未进行内存回收)

/**
 * 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) 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;
    }
};

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

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

递归法

思路

构造二叉树,前序遍历。

升序,左子树在左半边,右子树在右半边。

复杂度分析

时间复杂度:O(N)。遍历一遍数组。

空间复杂度:O(logN)。因为平衡。

注意点

  1. 注意循环不变量就好了。

代码实现

/**
 * 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* traversal(vector<int>& nums,int begin,int end){
        if(begin >= end) return NULL;
        int mid = (begin + end)/2;
        TreeNode* node = new TreeNode(nums[mid]);
        // 升序,左子树在左半边,右子树在右半边
        node->left = traversal(nums,begin,mid);
        node->right = traversal(nums,mid + 1,end);

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

迭代法

思路

双指针从中间向两边跑,根节点必须是数值大小中不溜的。

代码实现

我的递归想法:

其实也满足平衡树,但不是最平衡,这题只有最平衡的结果才能通过测试。

/**
 * 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() == 1) return new TreeNode(nums[0]);
        // 找中间节点,构造根节点
        int cur = nums.size()/2;
        int pre = cur - 1;
        TreeNode* root = new TreeNode(nums[cur]);
        cur++;
        TreeNode* node = root;
        while(pre >= 0 || cur < nums.size()){
            // cur右移
            if(cur < nums.size()){
                // 移到叶子节点
                while(node->left && node->right){
                    if(nums[cur] > root->val) node = node->right;
                    else if(nums[cur] < root->val) node = node->left;
                }
                if(nums[cur] > node->val) node->right = new TreeNode(nums[cur]);
                else if(nums[cur] < node->val) node->left = new TreeNode(nums[cur]);
                cur++;
            }
            // pre左移
            if(pre >= 0){
                // 移到叶子节点
                while(node->left && node->right){
                    if(nums[pre] > root->val) node = node->right;
                    else if(nums[pre] < root->val) node = node->left;
                }
                if(nums[pre] > node->val) node->right = new TreeNode(nums[pre]);
                else if(nums[pre] < node->val) node->left = new TreeNode(nums[pre]);
                pre--;
            }
        }

        return root;
    }
};

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

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

思路

要求:使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

所以从大到小遍历一遍,记录累加值,每个节点改为累加值。

中序遍历,不过是先右后左。

复杂度分析

时间复杂度:O(logN)。

空间复杂度:O(logN)/O(N)。

注意点

代码实现

/**
 * 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:
    // 中序遍历,不过是先右再左
    int sum = 0;
    TreeNode* convertBST(TreeNode* root) {
        if(!root) return NULL;
        root->right = convertBST(root->right);
        sum += root->val;
        root->val = sum;
        root->left = convertBST(root->left);
        
        return root;
    }
};
posted @ 2024-02-22 01:32  Tazdingo  阅读(1234)  评论(0)    收藏  举报