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

669. 修剪二叉搜索树

思路

  1. 截止条件:为空节点
  2. 单层递归:值如果小于low,值如果大于high,如果值在lowhigh之间,则递归左右节点
  3. 返回:返回根节点

代码

  1. 递归
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (!root) return nullptr;
        if (root->val < low) 
            return trimBST(root->right, low, high);
        if (root->val > high) 
            return trimBST(root->left, low, high); 
        if (root->val >= low && root->val <= high){
            root->left = trimBST(root->left, low, high);
            root->right = trimBST(root->right, low, high);
        }
        return root;
    }
};
  1. 迭代
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (!root) return nullptr;

        while (root != nullptr && (root->val < low || root->val > high)) {
            if (root->val < low) root = root->right; 
            else root = root->left;
        } // 找到在范围中的根节点

        auto cur = root;
        while (cur){
            while (cur->left && cur->left->val < low){
                cur->left = cur->left->right;
            }
            cur = cur->left;
        } // 找寻符合要求的左子树

        cur = root;
        while (cur){
            while (cur->right && cur->right->val > high){
                cur->right = cur->right->left;
            }
            cur = cur->right;
        }//找寻符合要求的右子树

        return root;
    }
};

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

思路

  1. 有序数组,中间对半分,左侧一直向左,右侧一直向右
  2. 有序数组,中间对半分,每次都递归左侧这部分作为左子树再构建,右侧作为右子树再构建一个,注意截止条件

代码

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return dfs(nums, 0, nums.size() - 1);
    }
    TreeNode* dfs(vector<int>& nums, int left, int right){
        if (left > right) return nullptr;
        int mid = (left + right) >> 1;
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = dfs(nums, left, mid - 1);
        root->right = dfs(nums, mid + 1, right);
        return root;
    }
};

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

思路

  1. 第一次中序遍历记录sum总和,第二次中序遍历更改val
  2. 右中左

代码

class Solution {
public:
    vector<int> a;
    int sum = 0;
    int cur = 0;
    TreeNode* convertBST(TreeNode* root) {
        dfs(root);
        return dfs1(root);
    }
    void dfs(TreeNode* root){
        if (!root) return;
        dfs(root->left);
        a.push_back(root->val);
        sum += root->val;
        dfs(root->right);
        return;
    }
    TreeNode* dfs1(TreeNode* root){
        if (!root) return nullptr;
        dfs1(root->left);
        cur = root->val;
        root->val = sum;
        sum -= cur;
        dfs1(root->right);
        return root;
    }
};
  1. 迭代
class Solution {
public:
    int pre = 0;
    TreeNode* convertBST(TreeNode* root) {
        if (!root) return nullptr;
        stack<TreeNode*> stk;
        auto cur = root;
        while (!stk.empty() || cur != nullptr){
            if (cur){
                stk.push(cur);
                cur = cur->right;
            }else{
                cur = stk.top();
                stk.pop();
                cur->val += pre;
                pre = cur->val;
                cur = cur->left;
            }
        }
        return root;
    }
};

总结

总结链接

遍历方式

前中后序 层序,迭代+递归

性质

  1. 二叉树:是否对称
    递归:后序,比较的是根节点的左子树与右子树是不是相互翻转
    迭代:使用队列/栈将两个节点顺序放入容器中进行比较
  2. 二叉树:求最大深度
    递归:后序,求根节点最大高度就是最大深度,通过递归函数的返回值做计算树的高度
    迭代:层序遍历
  3. 二叉树:求最小深度
    递归:后序,求根节点最小高度就是最小深度,注意最小深度的定义
    迭代:层序遍历
  4. 二叉树:求有多少个节点
    递归:后序,通过递归函数的返回值计算节点数量
    迭代:层序遍历
  5. 二叉树:是否平衡
    递归:后序,注意后序求高度和前序求深度,递归过程判断高度差
    迭代:效率很低,不推荐
  6. 二叉树:找所有路径
    递归:前序,方便让父节点指向子节点,涉及回溯处理根节点到叶子的所有路径
    迭代:一个栈模拟递归,一个栈来存放对应的遍历路径
  7. 二叉树:递归中如何隐藏着回溯
  8. 二叉树:求左叶子之和
    递归:后序,必须三层约束条件,才能判断是否是左叶子。
    迭代:直接模拟后序遍历
  9. 二叉树:求左下角的值(opens new window)
    递归:顺序无所谓,优先左孩子搜索,同时找深度最大的叶子节点。
    迭代:层序遍历找最后一行最左边
  10. 二叉树:求路径总和
    递归:顺序无所谓,递归函数返回值为bool类型是为了搜索一条边,没有返回值是搜索整棵树。
    迭代:栈里元素不仅要记录节点指针,还要记录从头结点到该节点的路径数值总和
    ………………
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值