当前位置: 首页 > news >正文

【4.7】图搜索算法-DFS和BFS解根到叶子节点数字之和

一、题目

        给定一个二叉树,它的每个结点都存放一个 0-9 的数字, 每条从根到叶子节点的路径都代表一个数字
        例如,从根到叶子节点路径 1->2->3 代表数字 123。计算从根到叶子节点生成的所有数字之和。
说明 : 叶子节点是指没有子节点的节点。
示例 1:
输入 : [ 1 , 2 , 3 ]
  1
 /  \
2   3
输出 : 25
解释 :
从根到叶子节点路径 1 ->2 代表数字 12 .
从根到叶子节点路径 1 ->3 代表数字 13 .
因此,数字总和 = 12 + 13 = 2 5
示例 2:
输入 : [ 4 , 9 , 0 , 5 , 1 ]
    4
   /  \
  9  0
 /  \
5  1
输出 : 1026
解释 :
从根到叶子节点路径 4 ->9 ->5 代表数字 495 .
从根到叶子节点路径 4 ->9 ->1 代表数字 491 .
从根到叶子节点路径 4 ->0 代表数字 40 .
因此,数字总和 = 495 + 491 + 40 = 1026 .

二、解题思路

DFS思路:

        这道题目要求计算从根节点到每个叶子节点的路径所代表的数字之和。每条路径上的数字可以通过将路径上的节点值按顺序连接起来形成一个数字。遍历一棵树从根节点到叶子节点的所有路径,最容易想到的方法是使用深度优先搜索(DFS),因此这题使用DFS是最容易解决的。

        解决方式是从根节点开始,沿着路径往下走时,当前节点的值可以通过父节点的值乘以10再加上当前节点的值来计算。默认根节点的父节点的值为0。当到达叶子节点时,将叶子节点的值加到一个全局变量中。这里以示例2为例,画个图来帮助理解。

BFS思路:

对于树的遍历,我们知道除了前序中序后续遍历以外,还有DFS和BFS,DFS上面已经讲过了,下面再来看一下BFS,他是一层一层的遍历的,就像下面这样

原理和上面DFS类似,每遍历一个结点,我们就要重新计算当前节点的值,那么当前节点的值就是父节点的值*10+当前节点的值。

三、代码实现

DFS代码:

        以例二来测试,由于输入数组 [4, 9, 0, 5, 1] 没有明确表示空节点,假设它表示的是一棵完全二叉树的前序遍历结果。如果实际的二叉树结构与假设不符,可能会导致构建的二叉树不正确。在这种情况下,需要更详细的信息来正确构建二叉树。

#include <iostream>
#include <vector>
#include <stack>using namespace std;// 定义二叉树节点结构
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};// 辅助函数:根据前序遍历数组构建二叉树
TreeNode* buildTree(vector<int>& preorder, int& index, int n) {if (index >= n) {return nullptr;}TreeNode* root = new TreeNode(preorder[index++]);root->left = buildTree(preorder, index, n);root->right = buildTree(preorder, index, n);return root;
}int sumNumbers(TreeNode* root) {// 如果根节点是空,直接返回0即可if (root == nullptr)return 0;// 两个栈,一个存储的是节点,一个存储的是节点对应的值stack<TreeNode*> nodeStack;stack<int> valueStack;// 全局的,统计所有路径的和int res = 0;nodeStack.push(root);valueStack.push(root->val);while (!nodeStack.empty()) {// 当前节点和当前节点的值同时出栈TreeNode* node = nodeStack.top();nodeStack.pop();int value = valueStack.top();valueStack.pop();if (node->left == nullptr && node->right == nullptr) {// 如果当前节点是叶子结点,说明找到了一条路径,把这条// 路径的值加入到全局变量res中res += value;} else {// 如果不是叶子节点就执行下面的操作if (node->right != nullptr) {// 把子节点和子节点的值分别加入到栈中,这里子节点的值// 就是父节点的值*10+当前节点的值nodeStack.push(node->right);valueStack.push(value * 10 + node->right->val);}if (node->left != nullptr) {nodeStack.push(node->left);valueStack.push(value * 10 + node->left->val);}}}return res;
}int main() {// 输入数组vector<int> preorder = {4, 9, 0, 5, 1};int index = 0;// 构建二叉树TreeNode* root = buildTree(preorder, index, preorder.size());// 计算路径数字之和int result = sumNumbers(root);cout << "路径数字之和: " << result << endl;return 0;
}

DFS代码精简为递归:

#include <iostream>
#include <vector>using namespace std;// 定义二叉树节点结构
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};// 辅助函数:根据前序遍历数组构建二叉树
TreeNode* buildTree(vector<int>& preorder, int& index, int n) {if (index >= n) {return nullptr;}TreeNode* root = new TreeNode(preorder[index++]);root->left = buildTree(preorder, index, n);root->right = buildTree(preorder, index, n);return root;
}// 辅助函数:计算从根到叶子节点的路径数字之和
void dfs(TreeNode* node, int currentSum, int& totalSum) {if (node == nullptr)return;// 计算当前路径的数字currentSum = currentSum * 10 + node->val;// 如果是叶子节点,将当前路径的数字加到总和中if (node->left == nullptr && node->right == nullptr) {totalSum += currentSum;return;}// 递归遍历左子树和右子树dfs(node->left, currentSum, totalSum);dfs(node->right, currentSum, totalSum);
}int sumNumbers(TreeNode* root) {int totalSum = 0;dfs(root, 0, totalSum);return totalSum;
}int main() {// 输入数组vector<int> preorder = {4, 9, 0, 5, 1};int index = 0;// 构建二叉树TreeNode* root = buildTree(preorder, index, preorder.size());// 计算路径数字之和int result = sumNumbers(root);cout << "路径数字之和: " << result << endl;return 0;
}

BFS代码:

#include <iostream>
#include <vector>
#include <queue>using namespace std;// 定义二叉树节点结构
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};// 辅助函数:根据前序遍历数组构建二叉树
TreeNode* buildTree(vector<int>& preorder, int& index, int n) {if (index >= n) {return nullptr;}TreeNode* root = new TreeNode(preorder[index++]);root->left = buildTree(preorder, index, n);root->right = buildTree(preorder, index, n);return root;
}int sumNumbers(TreeNode* root) {// 边界条件的判断if (root == nullptr)return 0;queue<TreeNode*> nodeQueue;queue<int> valueQueue;int res = 0;nodeQueue.push(root);valueQueue.push(root->val);while (!nodeQueue.empty()) {// 节点和节点对应的值同时出队TreeNode* node = nodeQueue.front();nodeQueue.pop();int value = valueQueue.front();valueQueue.pop();if (node->left == nullptr && node->right == nullptr) {// 如果当前节点是叶子结点,说明找到了一条路径,把这条// 路径的值加入到全局变量res中res += value;} else {// 如果不是叶子节点就执行下面的操作if (node->left != nullptr) {// 把子节点和子节点的值分别加入到队列中,这里子节点的值// 就是父节点的值*10+当前节点的值nodeQueue.push(node->left);valueQueue.push(value * 10 + node->left->val);}if (node->right != nullptr) {nodeQueue.push(node->right);valueQueue.push(value * 10 + node->right->val);}}}return res;
}int main() {// 输入数组vector<int> preorder = {4, 9, 0, 5, 1};int index = 0;// 构建二叉树TreeNode* root = buildTree(preorder, index, preorder.size());// 计算路径数字之和int result = sumNumbers(root);cout << "路径数字之和: " << result << endl;return 0;
}

        这道题目要求计算从根节点到每个叶子节点的路径所代表的数字之和。每条路径上的数字可以通过将路径上的节点值按顺序连接起来形成一个数字。我们要做的就是把这每个数字加起来。使用深度优先搜索(DFS)应该是最容易理解的,因为每条路径也可以被想象成一个链表,每个链表代表一个数字,然后把所有链表所代表的数字加起来就是这题要求的结果。

相关文章:

  • 2015年国赛高教杯数学建模A题太阳影子定位解题全过程文档及程序
  • OpenCV视频I/O(8)从视频源中读取一帧图像函数read()的使用
  • CDGA|数据治理:策略与价值的深度融合
  • CentOS 修改服务器登录密码的完整指南
  • 60.【C语言】内存函数(memset,memcmp函数)
  • 剖解环形链表1
  • 【nrm】npm 注册表管理器
  • STM32精确控制步进电机
  • 2025 年 IT 前景:机遇与挑战并存,人工智能和云计算成重点
  • Java面试:ArrayList 和 LinkedList 的区别是什么?谈谈你对ArrayList和LinkedList的理解
  • 基于深度学习的学情智能监测系统设计与实现(PYQT+YOLOv8+训练数据集+论文+部署文档)
  • we3.0里的钱包是什么?
  • 基于python+flask+mysql的音频信息隐藏系统
  • Llama 3.2 90B刚开源就被Molmo-72B全面击败!
  • SpringCloud入门
  • 时间复杂度分析经典问题——最大子序列和
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • [case10]使用RSQL实现端到端的动态查询
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • Apache Pulsar 2.1 重磅发布
  • CentOS7 安装JDK
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • magento2项目上线注意事项
  • Promise面试题2实现异步串行执行
  • Rancher-k8s加速安装文档
  • Terraform入门 - 1. 安装Terraform
  • vue-cli3搭建项目
  • 编写符合Python风格的对象
  • 工作中总结前端开发流程--vue项目
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 数组大概知多少
  • 微服务入门【系列视频课程】
  • 小程序测试方案初探
  • MPAndroidChart 教程:Y轴 YAxis
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #pragma pack(1)
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (26)4.7 字符函数和字符串函数
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (转)JAVA中的堆栈
  • (转)scrum常见工具列表
  • (转载)(官方)UE4--图像编程----着色器开发
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .DFS.
  • .mysql secret在哪_MySQL如何使用索引
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .net中我喜欢的两种验证码
  • /etc/shadow字段详解
  • @requestBody写与不写的情况