寻求二叉树中不相交叶到叶路径最大和的解决方案及学习资料
二叉树不相交叶到叶路径最大总和问题解决方案
问题分析
结合你提供的示例附图,你的需求是找到二叉树中不共享边的叶到叶路径集合,使得路径节点总和最大,且路径分叉的根节点不被计入总和。当前你的代码逻辑存在两个核心问题:
- 只考虑了单条路径或单个节点下的两条子路径组合,没有处理多组不相交路径的情况
- 错误地将当前节点值加入了单路径计算,不符合“分叉根节点不计入总和”的规则
你的示例附图:
你尝试的代码如下:
int depth(struct node *root, int *res) { if(root == NULL) return 0; int l = depth(root->left, res); int r = depth(root->right, res); int max_single_best_Way = max(l+root->data, r+root->data); int max_root = l+r; int maximum = max(max_single_best_Way, max_root); *res = max(*res, maximum); return maximum; }
算法思路建议
核心思路:后序遍历+树形DP
我们需要在遍历每个节点时维护两个关键状态,从叶子节点向上递归处理:
- 当前节点到下方叶子的最大单路径和:不计入当前节点值,用于向上传递可选路径
- 全局最大不相交路径总和:记录遍历过程中所有可行的不相交叶到叶路径组合的最大值
具体执行步骤:
- 叶子节点:单路径和为0(无后续节点),无法形成叶到叶路径,对全局总和无贡献
- 非叶子节点:
- 递归计算左右子树的单路径和
- 若同时存在左右子树,可形成一条叶到叶路径,其和为左右单路径和之和,直接更新全局最大值
- 当前节点的单路径和取左右子树单路径和的较大值(只能选择一条路径向上传递,避免边共享)
- 全局最大值还要对比左右子树各自的最大总和,确保不遗漏子树内部的最优解
修正后的可运行代码
#include <stdio.h> #include <stdlib.h> #include <limits.h> struct node { int data; struct node* left; struct node* right; }; struct node* newNode(int data) { struct node* node = (struct node*)malloc(sizeof(struct node)); node->data = data; node->left = NULL; node->right = NULL; return node; } int max(int a, int b) { return (a > b) ? a : b; } // 返回当前节点到叶子的最大单路径和,同时更新全局最大总和 int traverse(struct node* root, int* global_max) { if (root == NULL) return 0; // 叶子节点:无后续路径,单路径和为0 if (root->left == NULL && root->right == NULL) return 0; int left_single = traverse(root->left, global_max); int right_single = traverse(root->right, global_max); // 左右子树都存在时,计算当前叶到叶路径和并更新全局最大值 if (root->left != NULL && root->right != NULL) { int current_sum = left_single + right_single; *global_max = max(*global_max, current_sum); // 返回较大的单路径,用于上层节点组合 return max(left_single, right_single); } // 只有单侧子树时,直接返回对应子树的单路径和 return root->left != NULL ? left_single : right_single; } int maxDisjointLeafPathsSum(struct node* root) { int global_max = INT_MIN; traverse(root, &global_max); // 处理无叶到叶路径的情况(如单节点树) return global_max == INT_MIN ? 0 : global_max; } // 测试示例 int main() { struct node* root = newNode(1); root->left = newNode(2); root->right = newNode(3); root->left->left = newNode(4); root->left->right = newNode(5); root->right->left = newNode(6); root->right->right = newNode(7); printf("最大不相交叶到叶路径总和:%d\n", maxDisjointLeafPathsSum(root)); return 0; }
关键注意事项
- 路径不共享边:每个边只能属于一条路径,因此选择节点的左右子路径组合后,只能向上传递其中一条路径的信息
- 分叉根节点不计入总和:路径和仅包含叶子到分叉节点之间的子节点值,分叉节点本身不参与计算
学习资料推荐
- 二叉树后序遍历应用:重点掌握后序遍历在子树状态收集与合并中的核心逻辑,这是树形问题的基础
- 树形DP入门:学习树形动态规划的通用框架,掌握如何为每个节点定义状态并进行状态转移
- 路径和系列问题:先解决「二叉树最大叶到叶路径和」「二叉树最大路径和」等基础问题,再进阶到多路径不相交的场景
内容的提问来源于stack exchange,提问作者Aaron7
相关产品推荐
相关产品推荐

