【C++编程能力提升】

一、669 修剪二叉搜索树

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

核心:明确遇到待修剪的节点时应该如何操作
(1)当前节点值小于low,说明需要被修剪,还需要在其右子树寻找是否还存在要修剪的节点,直到遍历到的节点在区间内,无需修剪,此时将right返回到待修剪节点的上一层,即right会链接到被修剪节点的上一层;
(2)当前节点值大于high,说明需要被修剪,还需在其左子树寻找是否还存在要修剪的节点,直到遍历到符合区间要求的节点,此时无需修剪,并将left返回到待修剪节点的上一层;
(3)当前节点值符合区间要求,无需修剪,此时需要分别递归左、右子树寻找要修剪的节点。
注意:最后返回根节点root。

    TreeNode* trimBST(TreeNode* root, int low, int high) {
        //递归法:
        if(!root)
            return nullptr;
        //当前root是需要被修剪的,并在root右子树寻找符合区间[low,high]的节点
        if(root->val < low)
        {//root右子树上符合区间要求的节点right被返回到root的上一层(因为root被移除)
            TreeNode* right=trimBST(root->right,low,high);
            return right;   

        }
        //当前root也是要被修剪,并在root左子树寻找符合区间的节点
        else if(root->val > high)
        {//root左子树符合区间要求的节点left被返回至root的上一层
            TreeNode* left=trimBST(root->left,low,high);
            return left;
        }
        //当前root符合区间要求,无需修剪,需递归遍历左、右子树确定要修剪的节点
        root->left=trimBST(root->left,low,high);    //该root左孩子实质是接住right
        root->right=trimBST(root->right,low,high);
        return root;    //此时返回的依然是根节点
    }

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

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

核心:已知二叉搜索树的中序遍历数组是有序的(左中右),那么有序数组的中间元素一定是根节点root。
第一,由数组中间元素构造根节点;
第二,由左右区间分别递归构造左、右子树。

    //左闭右闭区间[left,right]
    TreeNode* traversal(vector<int>& nums,int left,int right)
    {//递归函数,先以中点为root,然后分割数组分别构造左右子数
        if(left>right)
            return nullptr; //区间为空,即nums为空
        //1。构造中点为root
        int mid=left+(right-left)/2;
        TreeNode* root=new TreeNode(nums[mid]);
        //2.分别递归构造左右子树,注意左右区间的取值
        root->left=traversal(nums,left,mid-1);
        root->right=traversal(nums,mid+1,right);
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return traversal(nums,0,nums.size()-1); //注意是左闭右闭区间
    }

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

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

核心:由于二叉搜索树的中序遍历是有序的,且从小到大,故本题实质是将中序遍历数组从后往前累加,直到数组的第一个元素,即按照反中序遍历进行累加,也就是说如果按照反中序(右中左)遍历二叉搜索树,只需从前往后累加即可,就是当前节点值为当前节点值和前一个节点值的累加。
具体实现方式有递归法和迭代法,两种方法都需要定义一个pre记录前一个节点值,以及每次累加结束需要更新pre。

    /*
    int pre=0;
    void traversal(TreeNode* node)
    {//递归函数:右中左
        if(!node)
            return; //记录前一个节点值
        traversal(node->right); //右
        node->val+=pre;         //中
        pre=node->val;  //更新pre
        traversal(node->left);  //左
    }
    */
    TreeNode* convertBST(TreeNode* root) {
        //迭代法:借助栈实现反中序遍历(右中左)
        stack<TreeNode*> stk;
        TreeNode* cur=root; //记录当前节点
        int pre=0;          //记录前一个节点值
        while(cur || !stk.empty())
        {
            if(cur)
            {
                stk.push(cur);
                cur=cur->right; //右
            }
            else
            {//cur==nullptr
                cur=stk.top();  //中
                stk.pop();
                cur->val+=pre;  //前一个节点值累加到当前节点
                pre=cur->val;   //更新pre
                cur=cur->left;  //左
            }
        }
        return root;
        /*
        //实质是中序遍历数组从后往前累加,等价于反中序遍历数组从前往后累加
        //递归法:反中序,右中左
        pre=0;
        traversal(root);
        return root;
        */
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值