代码随想录算法训练营day21

代码随想录算法训练营

—day21

文章目录

  • 代码随想录算法训练营
  • 前言
  • 一、669. 修剪二叉搜索树
    • 递归法
    • 迭代法
  • 二、108.将有序数组转换为二叉搜索树
    • 递归法
    • 迭代法
  • 三、538.把二叉搜索树转换为累加树
    • 递归法
  • 总结


前言

今天是算法营的第21天,希望自己能够坚持下来!
今日任务:
● 669. 修剪二叉搜索树
● 108. 将有序数组转换为二叉搜索树
● 538. 把二叉搜索树转换为累加树


一、669. 修剪二叉搜索树

题目链接
文章讲解
视频讲解

修剪过程如下:
在这里插入图片描述

节点0不符合范围,只需要删除节点0,将节点0的右子树赋值给节点3的左子树就可以了:
在这里插入图片描述

递归法

思路:

  1. 递归函数的参数和返回值:参数:当前传入节点和范围值。 返回值:修剪过后的根节点。
  2. 终止条件:遇到空节点为止
  3. 单层递归的逻辑:当前节点小于low,则左子树都会小于low,应该递归右子树,寻找能够当新节点的节点,并返回给上层;
  4. 当前节点大于high,则右子树都会大于high,应该递归左子树,寻找能当新节点的头节点,并返回给上层。
  5. root的左节点和右节点分别接收由下层递归返回的修剪过的新节点。
/**
 * 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 == nullptr) return nullptr; //遇到空节点返回

        //当前节点大于阈值,向左递归寻找符合范围的节点
        //当前节点小于阈值,向右递归寻找符合范围的节点
        if (root->val > high) return trimBST(root->left, low, high); 
        else 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;
    }
};

迭代法

因为二叉搜索树的有序性,不需要使用栈模拟递归的过程。

在剪枝的时候,可以分为三步:

  1. 将root移动到[L, R] 范围内,注意是左闭右闭区间
  2. 剪枝左子树
  3. 剪枝右子树

代码如下:

/**
 * 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 == nullptr) return nullptr;

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

        //修剪左子树
        TreeNode* cur = root;
        while (cur != nullptr) {
            while (cur->left && cur->left->val < low) { 
                cur->left = cur->left->right; //如果左节点不在范围内,则找左节点的右节点替换
            }
            cur = cur->left;        //找到了合适的新左节点,继续循环判断新左节点的左节点是否合适
        }

        cur = root; //重新从根节点开始
        while (cur != nullptr) {
            while (cur->right && cur->right->val > high) { //如果右节点不在范围内,则找右节点的左节点替换
                cur->right = cur->right->left;
            }
            cur = cur->right; //找到了合适的新右节点,继续循环判断新右节点的右节点是否合适
        }

        return root;
    }
};

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

题目链接
文章讲解
视频讲解

递归法

思路:
取数组的中间元素作为根节点,然后递归左区间和右区间继续以区间中间元素作为中间节点,构建二叉树要使用中序遍历。

代码如下:

/**
 * 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 {
private:
    TreeNode* traversal(vector<int>& nums, int left, int right) {
        if (left > right) return nullptr;

        //取区间中间元素作为中间节点,左闭右闭区间
        int mid = left + (right - left) / 2;
        TreeNode* root = new TreeNode(nums[mid]); //中
        root->left = traversal(nums, left, mid - 1);//左
        root->right = traversal(nums, mid + 1, right);//右

        return root;
    }

public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.size() == 0) return nullptr;

        return traversal(nums, 0, nums.size() - 1);
    }
};

迭代法

迭代法可以通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标。
代码如下:

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.size() == 0) return nullptr;

        TreeNode* root = new TreeNode(0);   // 初始根节点
        queue<TreeNode*> nodeQue;           // 放遍历的节点
        queue<int> leftQue;                 // 保存左区间下标
        queue<int> rightQue;                // 保存右区间下标
        nodeQue.push(root);                 // 根节点入队列
        leftQue.push(0);                    // 0为左区间下标初始位置
        rightQue.push(nums.size() - 1);     // nums.size() - 1为右区间下标初始位置

        while (!nodeQue.empty()) {
            TreeNode* curNode = nodeQue.front();
            nodeQue.pop();
            int left = leftQue.front(); leftQue.pop();
            int right = rightQue.front(); rightQue.pop();
            int mid = left + ((right - left) / 2);

            curNode->val = nums[mid];       // 将mid对应的元素给中间节点

            if (left <= mid - 1) {          // 处理左区间
                curNode->left = new TreeNode(0);
                nodeQue.push(curNode->left);
                leftQue.push(left);
                rightQue.push(mid - 1);
            }

            if (right >= mid + 1) {         // 处理右区间
                curNode->right = new TreeNode(0);
                nodeQue.push(curNode->right);
                leftQue.push(mid + 1);
                rightQue.push(right);
            }
        }
        return root;
    }
};

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

题目链接
文章讲解
视频讲解

在这里插入图片描述
从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了。
换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13]。

遍历顺序如图所示:
在这里插入图片描述

递归法

本题依然需要一个pre指针记录当前遍历节点cur的前一个节点,这样才方便做累加。
思路:

  1. 递归函数的参数和返回值:传入树的根节点,不需要返回值
  2. 终止条件:遇空就终止。
  3. 单层递归的逻辑:注意要右中左来遍历二叉树, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值。
/**
 * 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 pre = 0;
    void traversal(TreeNode* node) {
        if (node == nullptr) return;

        traversal(node->right); //右

        node->val += pre; //中,用pre记录上一个节点的值,与当前节点值累加
        pre = node->val; //更新上一个节点值

        traversal(node->left); //左 
        return;
    }

    //从题目的图中可看出,累加的顺序是右中左,所以反中序遍历二叉树,在用双指针依次累加即可
    TreeNode* convertBST(TreeNode* root) {
        pre = 0;
        traversal(root);
        return root;
    }
};

总结

二叉树终于结束了!来个总结:

  • 二叉树的递归:1.确定递归函数的参数 2.确定终止条件 3.单层递归逻辑
  • 二叉树的遍历方式:前序遍历(中左右),中序遍历(左中右),后序遍历(左右中)
  • 二叉树的迭代法,前序和后序相似,使用栈来存放需要处理的节点;而中序的栈是存放指针访问的节点,向左访问到最底层,再弹出节点进行处理,再向右访问。
  • 统一迭代法则是使用在需要处理的节点(中间节点)后面再放入空指针用来标记这是需要处理的节点,只有遇到空节点弹出时,才进行处理下一个节点
  • 二叉树的层序遍历:用队列模拟实现
  • 涉及到二叉树的构造,无论普通二叉树还是二叉搜索树一定前序,都是先构造中节点。
  • 求普通二叉树的属性,一般是后序,一般要通过递归函数的返回值做计算。
  • 求二叉搜索树的属性,一定是中序了,要不白瞎了有序性了。

下面是其他星球成员做的图,借用一下:
在这里插入图片描述

明天继续加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/947860.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jetson系列部署YOLOv8模型教程

简介 NVIDIA Jetson系列是专为边缘计算设计的紧凑型计算模块&#xff0c;其目标用户为AI开发者、嵌入式系统工程师以及需要在设备端实时进行数据处理与AI推断的创新者。通过提供灵活的硬件平台&#xff0c;结合NVIDIA强大的GPU计算资源&#xff0c;Jetson系列能够支持复杂的机…

Python 3 与 Python 2 的主要区别

文章目录 1. 语法与关键字print 函数整数除法 2. 字符串处理默认字符串类型字符串格式化 3. 输入函数4. 迭代器和生成器range 函数map, filter, zip 5. 标准库变化urllib 模块configparser 模块 6. 异常处理7. 移除的功能8. 其他重要改进数据库操作多线程与并发类型注解 9. 总结…

word中编号统一格式

不要手敲编号&#xff0c;要利用工具来。要善于利用多级编号和编号&#xff0c;分别对标题和段落进行组织 尤其是段落和标题特别多的时候&#xff0c;像毕设、标书这些 为什么呢&#xff1f;因为这样更方便修改&#xff0c;后续的增加和删除段落&#xff0c;编号会自动排列&am…

MySQL8安装与卸载

1.下载mysql MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2.解压mysql安装包 解压到自己定义的目录&#xff0c;这里解压就是安装&#xff0c;解压后的路径不要有空格和中文。 3.配置环境变量 配置环境变量可以方便电脑在任何的路径…

牛客网刷题 ——C语言初阶——JZ15 二进制中1的个数

1.题目描述 题目OJ链接 描述 输入一个整数 n &#xff0c;输出该数32位二进制表示中1的个数。其中负数用补码表示。 2.思路 求2进制中1的个数&#xff0c;可以转换为求每一位&#xff0c;1的个数&#xff0c;1&1还是1 所以判断如果该数值&1为真&#xff0c;我们就co…

SAP物料主数据界面增加客制化字段、客制化页签的方式

文章目录 前言一、不增加页签&#xff0c;只增加客制化字段二、增加物料主数据页签 前言 【SAP系统MM模块研究】 #SAP #MM #物料 #客制化 #物料主数据 项目上难免会遇到客户要在物料主数据的界面上&#xff0c;增加新字段的需求。 实现方式有&#xff1a; &#xff08;1&…

十一、Vue 自定义指令详解

文章目录 一、自定义指令概念二、自定义指令的基本语法全局自定义指令局部自定义指令三、指令钩子函数bindinsertedupdatecomponentUpdatedunbind四、指令的参数传递简单参数传递动态参数传递五、自定义指令的应用场景权限控制动画效果第三方库集成六、自定义指令的双向绑定双向…

《Spring Framework实战》1:Spring简介

欢迎观看《Spring Framework实战》视频教程 Spring简介 目录 1. Spring简介 2. Spring项目 3. Spring 能做什么&#xff1f; Spring 使 Java 简单化。 Spring 使 Java 现代化。 Spring 使 Java 富有成效。 Spring 使 Java 反应性。 Spring 使 Java 轻松上云。 Sprin…

利用KPaaS平台提升企业审批流程的透明度

企业的审批流程不仅影响决策效率&#xff0c;还直接关联到组织的透明度和运营效果。传统的审批流程通常由多个环节和系统构成&#xff0c;每一个环节都可能存在信息不对称的现象。例如&#xff0c;某一审批节点的负责人可能并不清楚当前的审批状态&#xff0c;而在其他环节&…

重塑信任与价值:MHX如何定义数字资产新规则

在全球经济逐步数字化的浪潮中&#xff0c;数字资产交易正以惊人的速度成为主流投资方式。然而&#xff0c;这个市场充满机遇的同时&#xff0c;也因规则不透明、风险过高等问题让许多投资者望而却步。在这样的背景下&#xff0c;MHX曼哈顿数字资产交易所以全新的思维和创新的交…

《向量数据库指南》——应对ElasticSearch挑战,拥抱Mlivus Cloud的新时代

在当今数据驱动的商业环境中,向量数据库的应用正变得愈加重要。随着人工智能和机器学习的快速发展,尤其是在自然语言处理、图像识别及推荐系统等领域,向量数据库以其强大的存储和检索能力,迎来了广泛的应用机会。然而,在实际应用中,企业在选择和实施向量数据库方案时,常…

基于SpringBoot的网上订餐系统(源码+数据库+文档)

亲测完美运行带论文&#xff1a;文末获取源码 文章目录 项目简介&#xff08;论文摘要&#xff09;运行视频包含的文件列表&#xff08;含论文&#xff09;前台运行截图后台运行截图 项目简介&#xff08;论文摘要&#xff09; 随着我国经济的飞速发展&#xff0c;人们的生活速…

【保姆级】sql注入之堆叠注入

一、堆叠注入的原理 mysql数据库sql语句的默认结束符是以";"号结尾&#xff0c;在执行多条sql语句时就要使用结束符隔 开,而堆叠注入其实就是通过结束符来执行多条sql语句 比如我们在mysql的命令行界面执行一条查询语句,这时语句的结尾必须加上分号结束 select * fr…

Linux(centos)安装 MySQL 8 数据库(图文详细教程)

前言 前几天写了个window系统下安装Mysql的博客&#xff0c;收到很多小伙伴私信需要Linux下安装Mysql的教程&#xff0c;今天这边和大家分享一下&#xff0c;话不多说&#xff0c;看教程。 一、删除以前安装的MySQL服务 一般安装程序第一步都需要清除之前的安装痕迹&#xff…

Segment Anything论文详细翻译【Part2:引言Introduction】

目录 写在前面 Introduction 第1段 第2段 第3段 第4段 第5段 第6段 第7段 第8段 第9段 第10段 第11段 第12段 Figure2 关键特点 图中具体内容 图例说明 写在前面 为啥要写这篇文章&#xff1f;因为找不到一篇写的特别好的【翻译并仔细解释】文章。网上大多千…

整数拼接(哈希表 枚举)

2068. 整数拼接 - AcWing题库 #include <bits/stdc.h> using namespace std;const int N 1e5 10;int n,k; int a[N]; int s[11][N]; //因为Ai < 10^9 10^9 是一个10位数&#xff0c;所以要*10^10 才能拼接int main() {cin >> n >> k;for (int i 1;i &…

使用爬虫技术获取网页中的半结构化数据

目录 前言1. 半结构化数据与爬虫技术简介1.1 半结构化数据的定义与特性1.2 爬虫技术的基本原理 2. 爬取半结构化数据的实现过程2.1 明确目标与准备2.2 发送HTTP请求2.3 解析网页内容2.4 动态内容的处理2.5 数据存储与清洗 3. 技术挑战与应对策略3.1 处理反爬机制3.2 提高爬取效…

Linux(Centos 7.6)命令详解:ls

1.命令作用 列出目录内容(list directory contents) 2.命令语法 Usage: ls [OPTION]... [FILE]... 3.参数详解 OPTION: -l&#xff0c;long list 使用长列表格式-a&#xff0c;all 不忽略.开头的条目&#xff08;打印所有条目&#xff0c;包括.开头的隐藏条目&#xff09…

一文读懂主成分分析法(PCA)

主成分分析法&#xff08;PCA&#xff09; 主成分分析法&#xff08;PCA&#xff09;主成分分析的基本思想主成分的计算主成分分析的原理主成分分析的特点主成分分析的应用 主成分分析法&#xff08;PCA&#xff09; 主成分分析的基本思想 PCA是1901 年Pearson在研究回归分析…

LLVM防忘录

目录 Windows中源码编译LLVMWindows下编译LLVM Pass DLL Windows中源码编译LLVM 直接从llvm-project下载源码, 然后解压后用VS2022打开该目录, 然后利用VS的开发终端执行: cmake -S llvm -B build -G "Visual Studio 17 2022" -DLLVM_ENABLE_PROJECTSclang -DLLVM_…