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

669. 修剪二叉搜索树

题目链接:669. 修剪二叉搜索树

非递归法

给出上下限,对二叉搜索树进行修剪。

对于下限,从根节点开始遍历,大于下限就前往左子树,等于下限就记录位置,小于下限就前往右子树直到大于等于下限,接回为记录位置的右节点;若根节点即小于下限,则根节点的右子树中大于下限的第一个节点为新的根节点。

对于上限,与下限逻辑相反。

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        TreeNode* cur = root;
        while(root->val < low || root->val > high){
            // 根节点小于下限
            if(root->val < low){
                cur = root;
                while(cur->val < low){
                    if(cur->right)  cur = cur->right;
                    else    return NULL;
                }
                root = cur;
            }
            // 根节点大于上限
            else if(root->val > high){
                cur = root;
                while(cur->val > high){
                    if(cur->left)   cur = cur->left;
                    else    return NULL;
                }
                root = cur;
            }
        }
        // 找下限
        while(1){
            cur = root;
            TreeNode* pre = cur;
            while(cur != NULL && cur->val >= low){
                pre = cur;
                cur = cur->left;
            }
            while(cur != NULL && cur->val < low){
                cur = cur->right;
            }
            pre->left = cur;
            // 验证最小值
            cur = root;
            while(cur->left){
                cur = cur->left;
            }
            if(cur->val >= low)  break;
        }
        
        // 找上限
        while(1){
            cur = root;
            TreeNode* pre = cur;
            while(cur != NULL && cur->val <= high){
                pre = cur;
                cur = cur->right;
            }
            while(cur != NULL && cur->val > high){
                cur = cur->left;
            }
            pre->right = cur;
            // 验证最大值
            cur = root;
            while(cur->right){
                cur = cur->right;
            }
            if(cur->val <= high)  break;
        }
        

        return root;
    }
};

我写了好长,看了下解析发现是绕圈子了;简单理清思路,应该是先把新根节点确定了,然后再左右确定上下界;

递归法

按照逻辑分析写的代码,有点繁琐,再考虑下递归法:

(1)参数:当前节点,上下界;返回值:节点;

(2)终止条件:节点为空;

(3)中间逻辑:若当前节点值大于上限,递归返回左孩子;若小于下限,递归返回右孩子;若在界内,递归左右孩子;

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if(root == NULL)    return NULL;
        if(root->val < low){
            root = trimBST(root->right, low, high);
        }
        else if(root->val > high){
            root = trimBST(root->left, low, high);
        }
        else{
            root->left = trimBST(root->left, low, high);
            root->right = trimBST(root->right, low, high);
        }
        return root;
    }
};

递归法代码不要简单太多啊!

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

题目链接:108. 将有序数组转换为二叉搜索树

递归法

这次思路很清晰,直奔递归,递归很好想。为了保持二叉搜索树的平衡,在一开始建树时,就平衡地来建最为保险;从有序数组中取出中位数作为根节点,然后两边作为子树,如此递归实现全部建树。

class Solution {
public:
    vector<int> value;
    TreeNode* setBST(int l, int r){
        if(r - l <= 0)    return NULL;
        int index = l + ((r - l) /2);
        TreeNode* node = new TreeNode(value[index]);
        node->left = setBST(l, index);
        node->right = setBST(index + 1, r);
        return node;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        value = nums;
        return setBST(0, nums.size());
    }
};

迭代法

迭代法的重点在于把该插入树中的数值找出来,我们用队列实现;

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if(nums.size() == 0)    return NULL;
        TreeNode* root = new TreeNode(0);
        queue<pair<int, int>> indexQue;
        queue<TreeNode*> nodeQue;
        indexQue.push({0, nums.size()});
        nodeQue.push(root);
        while(!nodeQue.empty()){
            int left = indexQue.front().first;
            int right = indexQue.front().second;    indexQue.pop();
            int mid = left + ((right - left) / 2);
            TreeNode* node = nodeQue.front();   nodeQue.pop();
            node->val = nums[mid];

            if(left < mid){
                node->left = new TreeNode(0);
                nodeQue.push(node->left);
                indexQue.push({left, mid});
            }
            if(right > mid + 1){
                node->right = new TreeNode(0);
                nodeQue.push(node->right);
                indexQue.push({mid + 1, right});
            }
        }
        return root;
    }
};

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

题目链接:538. 把二叉搜索树转换为累加树

思路

因为是大于等于当前节点值的累加,所以应当是按照中序遍历的倒序进行累加,所以可以按照右中左的顺序进行遍历;

递归法

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

迭代法

与中序遍历的迭代法一样。

class Solution {
public:
    TreeNode* convertBST(TreeNode* root) {
        if(root == NULL)    return NULL;
        stack<TreeNode*> st;
        st.push(root);
        int sum = 0;
        while(!st.empty()){
            TreeNode* node = st.top();  st.pop();
            if(node != NULL){
                if(node->left)  st.push(node->left);
                st.push(node);
                st.push(NULL);
                if(node->right) st.push(node->right);
            } else {
                node = st.top();    st.pop();
                sum += node->val;
                node->val = sum;
            }
        }
        return root;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值