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

二十一天继续打卡,今天的修剪二叉树跟只删除一个节点的逻辑不同,还是比较难想的,其他两题都用了二叉搜索树的中序遍历是有序数组的性质。


669.修剪二叉搜索树

题目链接

做题过程

  • 看题以为跟上题删除二叉搜索树中的节点一样,但上一题只是删除了一个节点

知识点

  • 如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。
  • 如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。
  • 接下来要将下一层处理完左子树的结果赋给root->left,处理完右子树的结果赋给root->right。

递归法

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

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

题目链接

做题过程

  • 用递归法做出来,用中序遍历构造二叉树,每次选择区间的中间节点作为分割点。

递归法

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

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

题目链接

做题过程

  • 用中序遍历加双指针做出来了,利用了二叉搜索树中序遍历为递增数组的性质

双指针

class Solution {
public:
    TreeNode* pre = nullptr;
    void traversal(TreeNode* cur) {
        if (cur == nullptr) return;
        traversal(cur->right);
        if (pre != nullptr) cur->val += pre->val;
        pre = cur;
        traversal(cur->left);
    }
    TreeNode* convertBST(TreeNode* root) {
        traversal(root);
        return root;
    }
};

二叉树总结

二叉树的理论基础


二叉树的遍历方式


求二叉树的属性

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

#二叉树的修改与构造

  • 翻转二叉树
    • 递归:前序,交换左右孩子
    • 迭代:直接模拟前序遍历
  • 构造二叉树
    • 递归:前序,重点在于找分割点,分左右区间构造
    • 迭代:比较复杂,意义不大
  • 构造最大的二叉树
    • 递归:前序,分割点为数组最大值,分左右区间构造
    • 迭代:比较复杂,意义不大
  • 合并两个二叉树
    • 递归:前序,同时操作两个树的节点,注意合并的规则
    • 迭代:使用队列,类似层序遍历

#求二叉搜索树的属性

  • 二叉搜索树中的搜索
    • 递归:二叉搜索树的递归是有方向的
    • 迭代:因为有方向,所以迭代法很简单
  • 是不是二叉搜索树
    • 递归:中序,相当于变成了判断一个序列是不是递增的
    • 迭代:模拟中序,逻辑相同
  • 求二叉搜索树的最小绝对差
    • 递归:中序,双指针操作
    • 迭代:模拟中序,逻辑相同
  • 求二叉搜索树的众数
    • 递归:中序,清空结果集的技巧,遍历一遍便可求众数集合
    • 二叉搜索树转成累加树
    • 递归:中序,双指针操作累加
    • 迭代:模拟中序,逻辑相同

#二叉树公共祖先问题

  • 二叉树的公共祖先问题
    • 递归:后序,回溯,找到左子树出现目标值,右子树节点目标值的节点。
    • 迭代:不适合模拟回溯
  • 二叉搜索树的公共祖先问题
    • 递归:顺序无所谓,如果节点的数值在目标区间就是最近公共祖先
    • 迭代:按序遍历

#二叉搜索树的修改与构造

  • 二叉搜索树中的插入操作
    • 递归:顺序无所谓,通过递归函数返回值添加节点
    • 迭代:按序遍历,需要记录插入父节点,这样才能做插入操作
  • 二叉搜索树中的删除操作
    • 递归:前序,想清楚删除非叶子节点的情况
    • 迭代:有序遍历,较复杂
  • 修剪二叉搜索树
    • 递归:前序,通过递归函数返回值删除节点
    • 迭代:有序遍历,较复杂
  • 构造二叉搜索树
    • 递归:前序,数组中间节点分割
    • 迭代:较复杂,通过三个队列来模拟
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值