ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

二叉树最深层叶子节点和的递归与迭代解法

二叉树最深层叶子节点和的递归与迭代解法 1. 题目解析与解题思路这道题目要求我们计算二叉树中最深层叶子节点的和。乍一看似乎很简单但实际处理时需要同时考虑树的深度遍历和特定层级的节点统计。作为刚接触树结构的新手我最初被这个看似简单的问题卡住了好几个小时。1.1 问题核心理解题目给出的二叉树结构定义如下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) {} };关键点在于需要先确定树的最大深度然后收集所有位于该深度的叶子节点最后将这些节点的值相加1.2 解题思路选择我最终选择了DFS深度优先搜索的递归解法原因如下递归天然适合处理树结构DFS可以自然地跟踪当前节点的深度相比BFS广度优先搜索需要维护队列DFS实现更简洁2. 代码实现详解2.1 最大深度计算int maxDepth; // 定义最大深度 void getMaxDepth(TreeNode* root, int depth) { if(root NULL) { // 递归终止条件 return; } if(maxDepth depth) { maxDepth depth; // 更新最大深度 } getMaxDepth(root-left, depth1); // 递归左子树 getMaxDepth(root-right, depth1); // 递归右子树 }这段代码有几个关键点需要注意maxDepth是类成员变量用于在递归过程中保持状态每次递归调用时当前深度depth会1遇到空节点时直接返回这是递归的终止条件2.2 最深层节点求和int sumMaxDepth(TreeNode* root, int depth) { if(root NULL) { return 0; } if(maxDepth depth) { return root-val; // 找到目标节点返回其值 } return sumMaxDepth(root-left, depth1) sumMaxDepth(root-right, depth1); }这个函数的逻辑同样以空节点作为递归终止条件当当前深度等于最大深度时返回该节点的值否则继续递归左右子树并将结果相加2.3 主函数整合int deepestLeavesSum(TreeNode* root) { maxDepth 0; getMaxDepth(root, 0); // 先计算最大深度 return sumMaxDepth(root, 0); // 再求和 }主函数的执行顺序很重要必须先计算最大深度然后才能基于这个深度求节点和3. 关键知识点解析3.1 递归在树结构中的应用树是递归定义的天然结构每个子树本身也是一棵树。这种自相似性使得递归成为处理树问题的利器。在本解法中我们利用递归实现了深度优先遍历深度信息的传递节点值的累加3.2 递归函数的返回值处理这里有一个很重要的细节getMaxDepth是void类型通过修改成员变量maxDepth来传递结果sumMaxDepth是int类型通过返回值传递计算结果这种差异反映了递归函数设计的两种常见模式通过参数或成员变量向下传递信息通过返回值向上传递计算结果4. 常见问题与优化思考4.1 空树处理当前代码已经考虑了空树的情况getMaxDepth遇到空节点直接返回maxDepth保持初始值0sumMaxDepth遇到空节点返回0最终和为04.2 递归深度限制对于极端不平衡的树如退化成链表递归可能导致栈溢出。这时可以考虑使用迭代代替递归改用BFS实现增加递归深度限制检查4.3 时间复杂度分析该算法的时间复杂度是O(n)其中n是节点数量因为计算最大深度需要遍历所有节点求和过程也需要遍历所有节点每个节点只被访问两次空间复杂度取决于树的高度最坏情况下是O(n)。5. 代码优化建议5.1 合并两次遍历当前解法遍历了两次树可以优化为一次遍历class Solution { public: int deepest 0; int sum 0; void dfs(TreeNode* node, int depth) { if(!node) return; if(depth deepest) { deepest depth; sum node-val; } else if(depth deepest) { sum node-val; } dfs(node-left, depth1); dfs(node-right, depth1); } int deepestLeavesSum(TreeNode* root) { dfs(root, 0); return sum; } };这个优化版本只遍历一次树动态更新最大深度和对应节点和减少了重复计算5.2 迭代实现方案对于不喜欢递归的开发者可以用迭代实现int deepestLeavesSum(TreeNode* root) { if(!root) return 0; queueTreeNode* q; q.push(root); int sum 0; while(!q.empty()) { int size q.size(); sum 0; // 重置当前层级的和 for(int i 0; i size; i) { TreeNode* node q.front(); q.pop(); sum node-val; if(node-left) q.push(node-left); if(node-right) q.push(node-right); } } return sum; }这个BFS实现按层级遍历树最后一层自然就是最深层不需要预先计算深度6. 学习心得与总结通过这道题目我深刻理解了递归在树结构中的应用。几个关键收获递归终止条件必须明确否则会导致无限递归递归函数的返回值类型决定了如何处理子问题的结果树的问题通常有多种解法DFS/BFS递归/迭代各有优缺点先理清思路再写代码比直接动手调试效率高得多对于树结构的练习我的建议是先掌握基本的遍历方式前序、中序、后序理解递归的工作原理多做练习题从简单到复杂逐步提升这道题目虽然让我纠结了很久但通过不断调试和思考最终不仅解决了问题还对树结构和递归有了更深的理解。这种通过实际问题驱动学习的方式效果比单纯看书要好得多。
返回列表