每日一题之二叉树

已知结点元素值为正整数且值不相同的一棵二叉树。
该二叉树通过给出其先序遍历序列和中序遍历序列构造而成。
输入一个整数x,针对此二叉树编写程序求出x的右子树中所有结点值的和(若x不在树上,输出-1)。 
输入说明:第一行输入某二叉树的先序遍历序列 第二行输入该二叉树的中序遍历序列 第三行输入正整数x 
输出说明:若x在树上,输出其右子树所有结点值的和(如果右子树为空,输出0);如果x不在树上则输出-1。 

输入样例:20 15 10 12 18 16 17 25 10 12 15 16 17 18 20 2515
输出样例:51

  在解决这道题之前,我们先来了解一个树的四种遍历方式:先序遍历、中序遍历、后序遍历、层序遍历。

​
#include<iostream>
#include<queue>
using namespace std;struct TreeNode{int val;TreeNode* left;TreeNode* right; TreeNode(int x):val(x),left(nullptr),right(nullptr){}
};void PreOrder(TreeNode* root);		//前序遍历 
void InOrder(TreeNode* root);		//中序遍历 
void PostOrder(TreeNode* root);		//后序遍历 
void LevelOrder(TreeNode* root);	//层序遍历 int main(){TreeNode* root=new TreeNode(1);root->left=new TreeNode(2);root->right=new TreeNode(3);root->left->left=new TreeNode(4);root->left->right=new TreeNode(4);root->right->left=new TreeNode(5);PreOrder(root);cout<<endl;InOrder(root);cout<<endl;PostOrder(root);cout<<endl;LevelOrder(root);cout<<endl; return 0;
}void PreOrder(TreeNode* root){if(!root){return ;}cout<<root->val<<" ";PreOrder(root->left);PreOrder(root->right);
} void InOrder(TreeNode* root){if(!root){return;}InOrder(root->left);cout<<root->val<<" ";InOrder(root->right);
}void PostOrder(TreeNode* root){if(!root){return ;}PostOrder(root->left);PostOrder(root->right);cout<<root->val<<" ";
}void LevelOrder(TreeNode* root){if(!root){return;}queue<TreeNode*> q;q.push(root);while(!q.empty()){TreeNode* cur=q.front();q.pop();cout<<cur->val<<" ";if(cur->left){q.push(cur->left);}if(cur->right){q.push(cur->right);}}//cout<<endl;
}​

前序遍历、中序遍历和后序遍历的思路都差不多,只不过要区分三种方式,其实前、中、后主要是指根节点的遍历顺序。

前序遍历(先序遍历)是指根结点先遍历,再依次遍历它的左右结点。

中序遍历是先遍历左子树结点,再遍历根节点,然后遍历右子树。

后序遍历是指先遍历完左右子树结点,再遍历根结点。

而层序遍历则需要借助队列辅助,简单来说就是需要一层一层去遍历,如下图:

假设我们需要层序遍历这棵树,那么我们需要将根结点A先放入队列,然后再将当前结点指向A,将队列头结点出队,然后输出当前结点的值A,再遍历当前结点的左右子树结点,即B、C。将B、C入队,然后进入下一次循环,B为当前队列头结点,那么将B出队,同时遍历B的左右子树结点D、E,同时将D、E入队。那么此时队列的元素为C(头结点)、D、E。所以将C出队,遍历它的左右子树结点F,再将F入队。此时队列元素为D、E、F。遍历D、E、F,都未遍历到左右子树,且都将它们出队,此时队列为空,循环结束。

现在回到这个题,它给出了二叉树的先序和中序遍历,然后给出目标值,要我们求出这棵树中是否存在目标值,再求出目标值的右子树之和。

简单分析一下,解决这道题的思路就是先根据先序和中序遍历求出树的根节点,然后找出目标值,返回其右子树的和。

#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;struct TreeNode {int val;TreeNode *left, *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} // 初始化节点
};// 使用先序和中序遍历构建二叉树
TreeNode* buildTree(const vector<int>& preorder, int preStart, int preEnd, const vector<int>& inorder, int inStart, int inEnd, unordered_map<int, int>& inMap) {if (preStart > preEnd || inStart > inEnd) return nullptr; // 若范围不合法,返回空节点// 创建根节点,根节点值为先序遍历的第一个元素TreeNode* root = new TreeNode(preorder[preStart]);int inRoot = inMap[root->val]; // 查找根节点在中序遍历中的位置int numsLeft = inRoot - inStart; // 计算左子树节点的数量// 递归构建左子树root->left = buildTree(preorder, preStart + 1, preStart + numsLeft, inorder, inStart, inRoot - 1, inMap);// 递归构建右子树root->right = buildTree(preorder, preStart + numsLeft + 1, preEnd, inorder, inRoot + 1, inEnd, inMap);return root; // 返回根节点
}// 计算某节点的右子树所有节点值的和
int sumRightSubtree(TreeNode* root) {if (!root) return 0; // 若节点为空,返回0// 递归计算左右子树的节点值之和并加上当前节点值return root->val + sumRightSubtree(root->left) + sumRightSubtree(root->right);
}// 在二叉树中查找值为x的节点,并返回其右子树的节点值和
int findAndSumRightSubtree(TreeNode* root, int x) {if (!root) return -1; // 若节点为空,返回-1if (root->val == x) return sumRightSubtree(root->right); // 找到目标节点,计算右子树节点值和int leftSearch = findAndSumRightSubtree(root->left, x); // 在左子树中递归查找if (leftSearch != -1) return leftSearch; // 如果在左子树中找到目标节点,直接返回结果return findAndSumRightSubtree(root->right, x); // 否则在右子树中递归查找
}int main() {vector<int> preorder, inorder;int x, n;// 输入先序遍历序列长度cout << "请输入先序遍历序列长度: ";cin >> n;// 输入先序遍历序列cout << "请输入先序遍历序列: ";preorder.resize(n);for (int i = 0; i < n; i++) cin >> preorder[i];// 输入中序遍历序列cout << "请输入中序遍历序列: ";inorder.resize(n);for (int i = 0; i < n; i++) cin >> inorder[i];// 输入目标值xcout << "请输入目标值x: ";cin >> x;// 构建inorder索引哈希表,用于快速定位节点在中序遍历中的位置unordered_map<int, int> inMap;for (int i = 0; i < n; i++) inMap[inorder[i]] = i;// 使用先序和中序遍历序列构建二叉树TreeNode* root = buildTree(preorder, 0, n - 1, inorder, 0, n - 1, inMap);// 查找值为x的节点的右子树节点值和,并输出结果int result = findAndSumRightSubtree(root, x);cout << result << endl;return 0;
}

根据先序和中序求二叉树的方式是先找根节点,两种遍历方式得到的序列同时开始查找,先序遍历的第一个数是根节点,然后再中序遍历中找到根节点,其左边的数就是左子树,右边的数就是右子树,以此类推,在两种遍历方式找到子树,再递推到整棵树。样例输出的数如下图所示:

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

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

相关文章

win10系统使用Visual Studio 2019或cmake编译SDL2为32位库时出现error C2118: 负下标winnt.h的解决方法

提示&#xff1a; 下图蓝体字中的VS2008是错误的&#xff0c;其实SDL.sln是用VS2010版本的软件开发的&#xff08;对于SDL-release-2.0.5.zip源码而言至少是这样&#xff0c;而2024-11-6为止SDL是2.30.9版本了&#xff0c;2.30.9版本则无需自己编译&#xff0c;只需下载带后缀…

推荐一款管道数据检索工具:Pipedata-Pro

Pipedata-Pro是一款专为设计石油、天然气、水和蒸汽管道及管道系统的工程师开发的应用程序。该应用程序提供了设计管道系统所需的工程数据&#xff0c;拥有一个全面的管道类型、配件和材料数据库。 软件特点&#xff1a; 1. 技术参数查询&#xff1a;Pipedata-Pro 提供关于管道…

算法竞赛(Python)-数组

文章目录 一 、排序算法二 、二分查找1 二分查找讲解2 二分查找题目&#xff08;1&#xff09;二分查找&#xff08;2&#xff09;在排序数组中查找元素的第一个和最后一个位置&#xff08;3&#xff09;两数之和 II - 输入有序数组 三、数组双指针1对撞指针对撞指针题目1&…

基于STM32的LCD1602显示Proteus仿真设计(仿真+程序+设计报告+讲解视频)

这里写目录标题 1.主要功能0. 资料清单&下载链接资料下载链接&#xff1a;2.仿真设计3. 程序设计4. 设计报告5. 框图 基于STM32的LCD1602显示Proteus仿真设计(仿真程序设计报告讲解视频&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a…

CPP贪心算法示例

设有n个正整数&#xff08;n ≤ 20&#xff09;&#xff0c;将它们联接成一排&#xff0c;组成一个最大的多位整数。 例如&#xff1a;n3时&#xff0c;3个整数13&#xff0c;312&#xff0c;343联接成的最大整数为&#xff1a;34331213 又如&#xff1a;n4时&#xff0c;4个整…

SpringBoot项目编译报错 类文件具有错误的版本 61.0, 应为 52.0

springboot项目在编译时报错&#xff1a; /Users/Apple/Developer/art/caicai/cai-api/dubbo-samples/1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-provider/src/main/java/org/apache/dubbo/springboot/demo/provider/ProviderApplication.java:22:32 java…

写一个 EventBus 实现微信小程序的发布订阅,支持全局消息通知、跨页面通信,高效好用!

eventBus.js 在微信小程序中实现发布/订阅模式可以通过创建一个简单的事件管理器来实现。这个事件管理器将负责注册事件监听器、触发事件以及移除监听器。下面是一个具体的实现示例&#xff1a; 1. 创建事件管理器 首先&#xff0c;我们创建一个单独的文件 eventBus.js 来管理…

东胜物流软件 AttributeAdapter.aspx SQL 注入漏洞复现

0x01 产品简介 东胜物流软件是青岛东胜伟业软件有限公司一款集订单管理、仓库管理、运输管理等多种功能于一体的物流管理软件。该公司初创于2004年11月(前身为青岛景宏物流信息技术有限公司),专注于航运物流相关环节的产品和服务。东胜物流信息管理系统货代版采用MS-SQLser…

PVE纵览-备份与快照指南

PVE纵览-备份与快照指南 文章目录 PVE纵览-备份与快照指南摘要1 备份与快照概述定义与区别备份与快照在PVE中的应用场景 2 PVE 备份功能详解备份类型与策略配置备份任务自动化备份管理 3 PVE 快照功能详解快照的工作原理快照的创建与恢复机制快照对系统性能的影响快照的使用场景…

Mac如何实现最简单的随时监测实时运行状态的方法

Mac book有着不同于Windows的设计逻辑与交互设计&#xff0c;使得Mac book有着非常棒的使用体验&#xff0c;但是在Mac电脑的使用时间过长时&#xff0c;电脑也会出现响应速度变慢或应用程序崩溃的情况&#xff0c;当发生的时候却不知道什么原因导致的&#xff0c;想要查询电脑…

JavaWeb合集23-文件上传

二十三 、 文件上传 实现效果&#xff1a;用户点击上传按钮、选择上传的头像&#xff0c;确定自动上传&#xff0c;将上传的文件保存到指定的目录中&#xff0c;并重新命名&#xff0c;生成访问链接&#xff0c;返回给前端进行回显。 1、前端实现 vue3AntDesignVue实现 <tem…

Leetcode 34 Find First and Last Position of Element in Sorted Array

题意&#xff1a;找到非严格递增的数组中和target相等的左右边界 https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/description/ 解答&#xff1a; 经典二分&#xff0c;找左右边界&#xff0c;要查看l是否满足题意 class Solution …

LinkedList和单双链表。

java中提供了双向链表的动态数据结构 --- LinkedList&#xff0c;它同时也实现了List接口&#xff0c;可以当作普通的列表来使用。也可以自定义实现链表。 单向链表&#xff1a;一个节点本节点数据下个节点地址 给定两个有序链表的头指针head1和head2&#xff0c;打印两个链表…

实现简易开屏弹窗

要实现一个简易的开屏弹窗&#xff0c;并展示一些文章内容&#xff0c;以下是一个简单的HTML和CSS实现。这个弹窗会在页面加载时显示&#xff0c;并包含一个标题和一些文章内容。用户可以点击按钮关闭弹窗&#xff0c;关闭后&#xff0c;弹窗的状态会保存在浏览器的 sessionSto…

WPF之iconfont(字体图标)使用

1&#xff0c;前文&#xff1a; WPF的Xaml是与前端的Html有着高度相似性的标记语言&#xff0c;所以Xaml也可同Html一般轻松使用阿里提供的海量字体图标&#xff0c;从而有效的减少开发工作度。 2&#xff0c;下载字体图标&#xff1a; 登录阿里图标库网iconfont-阿里巴巴矢量…

图神经网络(GNN)入门笔记(2)——从谱域理解图卷积,ChebNet和GCN实现

一、谱域图卷积&#xff08;Spectral Domain Graph Convolution&#xff09; 与谱域图卷积&#xff08;Spectral Domain Graph Convolution&#xff09;对应的是空间域&#xff08;Spatial Domain&#xff09;图卷积。本节学习的谱域图卷积指的是通过频率来理解卷积的方法。 …

leetcode92:反转链表||

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a;[1,4,3,2…

知识图谱是如何通过数据集构建的,比如通过在MSCOCO和Flickr30k数据集和Visual Genome数据集

系列博客目录 文章目录 系列博客目录1. 数据准备与实体识别2. 关系抽取3. 图结构构建4. 图嵌入学习5. 知识图谱存储与查询示例&#xff1a;通过 Visual Genome 构建一个简单的知识图谱 构建知识图谱通常涉及从数据集中提取实体和关系&#xff0c;并将其结构化为图的形式。在 MS…

Python-安装与PyCharm的安装配置(1)

目录 安装 打开运行 PyCharm的安装 新建项目 安装 找到官网下载对应的电脑对应的版本 Welcome to Python.org -- 官网 下载稳定版的 安装记得勾选配置环境&#xff0c;这样自己就不需要再配置环境了 安装成功 至此python的运行环境就安装好了 打开运行 在开始菜单中可以…

XGBoost算法Python代码实现(单棵树类)

### XGBoost单棵树类 class XGBoost_Single_Tree(BinaryDecisionTree):# 结点分裂方法def node_split(self, y):# 中间特征所在列feature int(np.shape(y)[1]/2)# 左子树为真实值&#xff0c;右子树为预测值y_true, y_pred y[:, :feature], y[:, feature:]return y_true, y_p…