练习题(2024/4/29)

news2024/12/24 2:14:50

 在深度优先遍历中:有三个顺序,前中后序遍历 这里前中后,其实指的就是中间节点的遍历顺序,只要记住 前中后序指的就是中间节点的位置就可以了。

如图

1二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

输入:root = [1,null,2,3]
输出:[1,2,3]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

示例 5:

输入:root = [1,null,2]
输出:[1,2]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100
递归思路:

递归是一种在算法中使用函数自身来解决问题的方法。在递归算法中,函数会重复调用自身来处理问题的每一步,直到达到某个终止条件为止。递归算法通常包括三个重要部分:

  1. 确定递归函数的参数和返回值:确定哪些参数是递归过程中需要处理的,以及每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件:为了避免无限循环或栈溢出错误,在递归算法中必须定义递归终止的条件,当满足终止条件时递归停止。

  3. 确定单层递归的逻辑:确定每一层递归需要处理的信息,并实现递归过程。通常在单层递归的逻辑中包含当前节点的处理逻辑以及对子节点的递归调用。

在递归算法中,需要注意以下几点:

  1. 确定递归函数的参数和返回值:在这段代码中,递归函数的参数为当前节点指针和存储节点值的数组,返回类型为void。这样做可以处理当前节点的值并在递归过程中更新结果数组。

  2. 确定终止条件:在递归中,一定要有终止条件,否则会导致栈溢出错误。在这段代码中,终止条件是当前节点为空(cur == NULL),此时直接返回,结束当前递归。

  3. 确定单层递归的逻辑:在前序遍历中,需要先处理当前节点的值,然后递归遍历左子树,最后递归遍历右子树。这种顺序符合前序遍历的要求。

代码:

class Solution {
public:
    // 定义一个辅助函数,用来递归遍历二叉树并将节点值存入结果数组
    void traversal(TreeNode* cur, vector<int>& vec) {
        // 若当前节点为空,则返回
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 中序遍历,将当前节点的值加入结果数组
        traversal(cur->left, vec);  // 递归遍历左子树
        traversal(cur->right, vec); // 递归遍历右子树
    }
    
    // 定义前序遍历函数,返回一个存储节点值的数组
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        // 从根节点开始遍历
        traversal(root, result); // 调用辅助函数,从根节点开始前序遍历
        return result;
    }
};
 迭代思路:

迭代的思想是通过循环重复执行某段代码来解决问题,而不是通过递归的方式调用函数自身。迭代通常通过循环结构来实现,每次循环迭代处理一部分信息,直到达到预定的终止条件为止。

栈的特点是一种后进先出(LIFO)的数据结构,即最后入栈的元素会最先出栈

前序遍历的迭代法思路是通过使用栈数据结构来模拟递归的过程。具体步骤如下:

  1. 创建一个栈(stack)用于存储节点指针和一个结果数组(result)用于存储节点值。

  2. 将根节点压入栈中。

  3. 循环执行以下操作,直到栈为空:
    a. 弹出栈顶节点(当前访问的节点)。
    b. 将节点值加入结果数组。
    c. 如果节点的右子节点不为空,则将右子节点压入栈中。
    d. 如果节点的左子节点不为空,则将左子节点压入栈中。

  4. 遍历结束后,返回结果数组作为前序遍历的结果。

代码:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;  // 定义栈用来存储节点指针
        vector<int> result;   // 定义结果数组
        if (root == NULL) return result;  // 如果根节点为空则直接返回空数组
        st.push(root);  // 将根节点压入栈中
        while (!st.empty()) {
            TreeNode* node = st.top();  // 获取栈顶节点
            st.pop();  // 弹出栈顶节点
            result.push_back(node->val);  // 将节点值加入结果数组
            if (node->right) st.push(node->right);  // 若右子节点不为空,则压入栈中
            if (node->left) st.push(node->left);  // 若左子节点不为空,则压入栈中
        }
        return result;  // 返回结果数组
    }
};

2二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 

示例 1:

输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点的数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100
递归思路 代码:
class Solution {
public:
    // 定义一个辅助函数,用来递归遍历二叉树并将节点值存入结果数组(后序遍历)
    void traversal(TreeNode *cur, vector<int>& vec) {
        if (cur == nullptr) return;
        traversal(cur->left, vec);   // 递归遍历当前节点的左子树
        traversal(cur->right, vec);  // 递归遍历当前节点的右子树
        vec.push_back(cur->val);     // 将当前节点的值加入结果数组
    }

    // 定义后序遍历函数,返回一个存储节点值的数组
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);     // 开始后序遍历,将结果存入数组
        return result;
    }
};
迭代思路
  1. 栈的应用:题目要求实现二叉树的后序遍历,可以考虑使用栈来辅助实现。栈可以帮助我们模拟递归的过程,从而遍历树的节点。

  2. 迭代法的核心:迭代法的核心是通过循环结构不断处理节点,模拟递归的过程。在后序遍历中,节点的访问顺序是左子树、右子树、根节点,因此我们需要注意入栈的顺序。

  3. 遍历过程:从根节点开始,将根节点入栈。然后循环执行以下步骤:

    • 弹出栈顶节点,将其值加入结果数组。
    • 如果节点有右子节点,则将右子节点压入栈中。
    • 如果节点有左子节点,则将左子节点压入栈中。
  4. 结果反转:由于后序遍历的顺序是左子树、右子树、根节点,而我们入栈的顺序是根节点、右子节点、左子节点,因此得到的结果数组需要进行反转。

  5. 返回结果:最后返回反转后的结果数组即可。

代码:
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;  // 定义栈用来存储节点指针
        vector<int> result;   // 定义结果数组
        if (root == NULL) return result;  // 如果根节点为空则直接返回空数组
        st.push(root);  // 将根节点压入栈中
        while (!st.empty()) {
            TreeNode* node = st.top();  // 获取栈顶节点
            st.pop();  // 弹出栈顶节点
            result.push_back(node->val);  // 将节点值加入结果数组
            if (node->left) st.push(node->left);  // 若左子节点不为空,则压入栈中
            if (node->right) st.push(node->right);  // 若右子节点不为空,则压入栈中
        }
        reverse(result.begin(), result.end());  // 将结果数组反转,得到左右中的遍历顺序
        return result;  // 返回结果数组
    }
};

3二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100
递归思路 代码:
class Solution {
public:
    // 定义一个辅助函数,用来递归遍历二叉树并将节点值存入结果数组(中序遍历)
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == nullptr) return;
        traversal(cur->left, vec);      // 递归遍历当前节点的左子树
        vec.push_back(cur->val);        // 将当前节点的值加入结果数组
        traversal(cur->right, vec);     // 递归遍历当前节点的右子树
    }

    // 定义中序遍历函数,返回一个存储节点值的数组
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);        // 开始中序遍历,将结果存入数组
        return result;
    }
};
 迭代思路
  1. 栈的应用:使用栈来辅助实现中序遍历。栈可以帮助我们模拟递归的过程,从而遍历树的节点。

  2. 指针的运用:我们使用一个指针cur来遍历节点,初始时指向根节点。

  3. 循环遍历:我们使用一个while循环来遍历节点,直到当前节点为NULL且栈为空为止。在循环中,我们检查当前节点cur是否为空,以及栈是否为空。

  4. 处理当前节点

    • 如果cur不为空,说明还有左子树未遍历完,此时我们将当前节点入栈,并将cur指向其左子节点,以便继续向左遍历。
    • 如果cur为空,说明左子树已经遍历完毕,我们从栈中取出节点进行处理。这个节点就是当前子树的根节点,我们将其值加入结果数组,并将cur指向当前节点的右子节点。
  5. 遍历过程

    • 不断将左子节点入栈,直到到达最左侧节点。在入栈的过程中,保证了左、中、右的顺序。
    • 当一个节点的左子树全部处理完毕后,从栈中取出节点进行处理,然后转向处理右子树。
  6. 返回结果:最终返回中序遍历的结果数组。

代码:
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;  // 定义结果数组
        stack<TreeNode*> st;  // 定义栈用来存储节点指针
        TreeNode* cur = root;  // 初始化当前节点为根节点
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) {  // 如果当前节点不为空
                st.push(cur);  // 将当前节点入栈
                cur = cur->left;  // 移动到左子节点
            } else {
                cur = st.top();  // 从栈中取出节点进行处理
                st.pop();  // 弹出栈顶节点
                result.push_back(cur->val);  // 将节点值加入结果数组
                cur = cur->right;  // 移动到右子节点
            }
        }
        return result;  // 返回结果数组
    }
};

4学生们参加各科测试的次数

学生表: Students

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| student_id    | int     |
| student_name  | varchar |
+---------------+---------+
在 SQL 中,主键为 student_id(学生ID)。
该表内的每一行都记录有学校一名学生的信息。

科目表: Subjects

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| subject_name | varchar |
+--------------+---------+
在 SQL 中,主键为 subject_name(科目名称)。
每一行记录学校的一门科目名称。

考试表: Examinations

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| student_id   | int     |
| subject_name | varchar |
+--------------+---------+
这个表可能包含重复数据(换句话说,在 SQL 中,这个表没有主键)。
学生表里的一个学生修读科目表里的每一门科目。
这张考试表的每一行记录就表示学生表里的某个学生参加了一次科目表里某门科目的测试。

查询出每个学生参加每一门科目测试的次数,结果按 student_id 和 subject_name 排序。

查询结构格式如下所示。

示例 1:

输入:
Students table:
+------------+--------------+
| student_id | student_name |
+------------+--------------+
| 1          | Alice        |
| 2          | Bob          |
| 13         | John         |
| 6          | Alex         |
+------------+--------------+
Subjects table:
+--------------+
| subject_name |
+--------------+
| Math         |
| Physics      |
| Programming  |
+--------------+
Examinations table:
+------------+--------------+
| student_id | subject_name |
+------------+--------------+
| 1          | Math         |
| 1          | Physics      |
| 1          | Programming  |
| 2          | Programming  |
| 1          | Physics      |
| 1          | Math         |
| 13         | Math         |
| 13         | Programming  |
| 13         | Physics      |
| 2          | Math         |
| 1          | Math         |
+------------+--------------+
输出:
+------------+--------------+--------------+----------------+
| student_id | student_name | subject_name | attended_exams |
+------------+--------------+--------------+----------------+
| 1          | Alice        | Math         | 3              |
| 1          | Alice        | Physics      | 2              |
| 1          | Alice        | Programming  | 1              |
| 2          | Bob          | Math         | 1              |
| 2          | Bob          | Physics      | 0              |
| 2          | Bob          | Programming  | 1              |
| 6          | Alex         | Math         | 0              |
| 6          | Alex         | Physics      | 0              |
| 6          | Alex         | Programming  | 0              |
| 13         | John         | Math         | 1              |
| 13         | John         | Physics      | 1              |
| 13         | John         | Programming  | 1              |
+------------+--------------+--------------+----------------+
解释:
结果表需包含所有学生和所有科目(即便测试次数为0):
Alice 参加了 3 次数学测试, 2 次物理测试,以及 1 次编程测试;
Bob 参加了 1 次数学测试, 1 次编程测试,没有参加物理测试;
Alex 啥测试都没参加;
John  参加了数学、物理、编程测试各 1 次。

思路:

使用join语句将学生表 (students) 和课程表 (subjects) 进行连接,以获取学生和课程的相关信息。使用left join语句将考试表 (examinations) 与学生、课程表进行左连接,确保即使某些学生没有参加考试,也能包括在结果中。

在on子句中,通过学生ID和课程名进行连接条件的指定,以便获取正确的考试记录。

使用count()函数统计每位学生在每门课程上参加的考试次数,起别名为attended_exams。

使用group by子句按照学生ID和课程名进行分组,以便对每个学生每门课程进行统计。

最后使用order by子句按照学生ID和课程名进行排序,以便输出结果。

代码:

select st.student_id, st.student_name, su.subject_name, count(e.subject_name) as attended_exams
from Students as st
join Subjects as su  -- 连接学生表和课程表
left join Examinations as e  -- 左连接考试表
on st.student_id = e.student_id and e.subject_name = su.subject_name  -- 根据学生ID和课程名进行连接
group by st.student_id, su.subject_name  -- 按学生ID和课程名分组
order by st.student_id, su.subject_name;  -- 按学生ID和课程名排序

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3+Nuxt3 从0到1搭建官网项目(SEO搜索、中英文切换、图片懒加载)

Vue2Nuxt2 从 0 到1 搭建官网~ 想开发一个官网&#xff0c;并且支持SEO搜索&#xff0c;当然离不开我们的 Nuxt &#xff0c;Nuxt2 我们刚刚可以熟练运用&#xff0c;现在有出现了Nuxt3&#xff0c;那通过本篇文章让我们一起了解一下。 安装 Nuxt3 // npx nuxilatest init &…

乐观锁悲观锁

视频&#xff1a;什么是乐观锁&#xff1f;什么是悲观锁&#xff1f;_哔哩哔哩_bilibili

Leetcode—2739. 总行驶距离【简单】

2024每日刷题&#xff08;121&#xff09; Leetcode—2739. 总行驶距离 实现代码 class Solution { public:int distanceTraveled(int mainTank, int additionalTank) {int consume 0;int ans 0;while(mainTank ! 0) {mainTank--;consume;if(consume 5 && additio…

数据分析案例-全球表面温度数据可视化与统计分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

基于SpringBoot+Vue高校汉服租赁网站的设计与实现

项目介绍&#xff1a; 高校汉服租赁网站管理系统按照操作主体分为管理员和用户。管理员的功能包括字典管理、交流论坛管理、公告资讯管理、汉服信息管理、汉服收藏管理、汉服评价管理、汉服租赁管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库&#xff0c…

03 后端入参校验:自定义注解实现

03 后端入参校验&#xff1a;自定义注解实现 一、前言二、实现1、新建Spring Boot项目2、引入依赖3、新建注解类4、新建校验器5、全局异常处理器6、编写Controller7、新建实体类8、启动并测试 一、前言 在 Java 后端开发中&#xff0c;为了实现入参校验&#xff0c;常常会使用…

外径合格与否对线缆品质有着直接影响 应用测径仪很重要

关键词&#xff1a;测径仪,线缆测径仪,电缆测径仪,外径测量仪,线缆,电缆 电缆尺寸不合格的危害 1、传输性能下降&#xff1a;尺寸不合格会导致电线电缆的参数不符合设计要求&#xff0c;从而影响传输的速率和稳定性&#xff0c;从而导致数据传输缓慢&#xff0c;影响用户的使用…

PC 自动化测试入门 - pywinauto 上篇:初识

文章目录 前言PC 自动化测试 是什么&#xff1f;常用 PC 自动化测试工具pywinauto 是什么&#xff1f;Windows上支持的可访问性技术列表 操作记事本自动写入问题app Application(backend"uia").start("notepad.exe") 无法正常启动组件选择器和 print_cont…

使用这 7 个绩效评估模板简化您的员工评估

绩效评估受到了不好的评价&#xff1b;员工发现它们压力很大&#xff0c;而管理者则发现它们很耗时。 但随着绩效管理成为 2024 年人力资源的首要任务&#xff0c;也许是时候重新思考了。绩效评估模板可以帮助减轻评估过程的麻烦。通过为管理者提供一种简单、标准化的方法来评…

CVE-2024-3116 PgAdmin8.4代码执行漏洞

前言 在有闲情的时候&#xff0c;看了一下最近的CVE&#xff0c;看到了pgAdmin4在8.4版本之前存在着一个远程代码执行漏洞&#xff0c;因为pgAdmin4在github是开源的&#xff0c;网上也没有看到分析文章&#xff0c;于是就把源码下载了下来&#xff0c;根据漏洞的描述大致的分…

Linux服务器终端软件termius以及Xshell + WinSCP组合

1. termius 官网地址&#xff1a;https://termius.com/ Termius是一个跨平台的SSH客户端&#xff0c;它提供了一个便捷的方式来远程连接和管理服务器、虚拟机和网络设备。以下是Termius的一些特点和功能&#xff1a; 跨平台支持&#xff1a;Termius可在多个操作系统上运行&…

JS事件循环、宏任务与微任务

在JavaScript中&#xff0c;事件循环&#xff08;Event Loop&#xff09;是处理异步操作的核心机制。它负责执行代码&#xff0c;处理事件&#xff0c;并在适当的时候调度回调。为了更好地理解JavaScript的执行模型&#xff0c;我们需要深入探讨事件循环、宏任务&#xff08;Ma…

分布式与一致性协议之Raft算法(二)

Raft算法 什么是任期 我们知道&#xff0c;议会选举中的领导者是有任期的&#xff0c;当领导者任命到期后&#xff0c;需要重新再次选举。Raft算法中的领导者也是有任期&#xff0c;每个任期由单调递增的数字(任期编号)标识。比如&#xff0c;节点A的任期编号是1。任期编号会…

基于Docker + Locust的数据持久化性能测试系统

前几天给大家分享了如何使用Locust进行性能测试&#xff0c;但是在实际使用中会发现存在压测的结果无法保存的问题&#xff0c;比如在分布式部署情况下进行压测&#xff0c;每轮压测完成需要释放资源删除容器重新部署后&#xff0c;这段时间的压测结果就都丢失了&#xff0c;如…

Nacos 安全零信任实践

作者&#xff1a;柳遵飞 Nacos 作为配置中心经常存储一些敏感信息&#xff0c;但是由于误用导致安全风险&#xff0c;最常见的主要是以下两个问题&#xff1a; 1&#xff09;Nacos 暴露公网可以吗&#xff1f;不可以&#xff0c;因为 Nacos 定位是注册配置中心&#xff0c;是…

【STM32+HAL】SDIO模式读写SD卡

一、准备工作 有关CUBEMX的初始化配置&#xff0c;参见我的另一篇blog&#xff1a;【STM32HAL】CUBEMX初始化配置 二、所用工具 1、芯片&#xff1a; STM32F407ZGT6 2、IDE&#xff1a; MDK-Keil软件 3、库文件&#xff1a;STM32F4xxHAL库 三、实现功能 实现用DMA读写SD卡内…

Hadoop3:集群搭建及常用命令与shell脚本整理(入门篇,从零开始搭建)

一、集群环境说明 1、用VMware安装3台Centos7.9虚拟机 2、虚拟机配置&#xff1a;2C&#xff0c;2G内存&#xff0c;50G存储 3、集群架构 从表格中&#xff0c;可以看出&#xff0c;Hadoop集群&#xff0c;主要有2部分&#xff0c;一个是HDFS服务&#xff0c;一个是YARN服务 …

CSS中的层叠上下文

HTML 文档中的三维概念 平时我们从设备终端看到的 HTML 文档都是一个平面的&#xff0c;事实上 HTML 文档中的元素却是存在于三个维度中。除了大家熟悉的平面画布中的 x 轴和 y 轴&#xff0c;还有控制第三维度的 z 轴。 其中 x 轴通常用来表示水平位置&#xff0c;y 轴来表示…

力扣刷题Day2

题目链接&#xff1a; 24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 效果&#xff1a; 解题思路&#xff1a; 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 注意不可以只是单纯的改变节点内部的值&#xff0c;而…

面试:MYSQL(SQL优化、MYSQL事务)

目录 一、SQL优化 1、如何定位慢查询 &#xff08;1&#xff09;方案一&#xff1a;开源工具 &#xff08;2&#xff09;方案二&#xff1a;慢日志查询 2、定位到慢查询时&#xff0c;如何优化 3、什么是索引 &#xff08;1&#xff09;底层结构 4、聚簇索引&#xff0…