LeetCode 124 二叉树最大路径和变种实现问题:如何修正代码以返回正确的最大路径和及完整路径
问题分析与解决方案
你的代码目前存在两个核心问题,导致无法正确输出路径和计算最大路径和:
- 路径记录错误:你当前存储的
self.path是左右子树的最大和与当前节点值,而不是实际的节点序列——比如用例2中[6,10,7]里的6其实是8 + (-2)的和,并不是节点值本身。 - 未处理单侧延伸的长路径:你的逻辑只考虑了「以当前节点为顶点,左右子树都贡献」的情况,但像用例3中那种从3→6→9→0→-1→10的单侧延伸链状路径,你的代码完全没捕捉到,因为递归返回的是单侧最大和,但你没有跟踪这种路径的节点序列。
修正思路
我们需要在递归时,不仅返回当前节点向下延伸的单侧最大和,还要返回对应的单侧路径节点列表(比如从当前节点到子树某节点的完整路径)。同时,在遍历每个节点时,需要考虑四种可能的路径情况:
- 仅当前节点本身
- 当前节点 + 左子树的单侧路径
- 当前节点 + 右子树的单侧路径
- 当前节点 + 左子树单侧路径 + 右子树单侧路径(即当前节点为顶点的跨左右路径)
每一步都更新全局的最大路径和与对应的完整路径,确保不会遗漏任何潜在的最优解。
修正后的代码
class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right @staticmethod def to_binary_tree(items): """Generate a BT from a given list""" n = len(items) if n == 0: return None def inner(index: int = 0): """Closure function using recursion to build tree""" if n <= index or items[index] is None: return None node = TreeNode(items[index]) node.left = inner(2 * index + 1) node.right = inner(2 * index + 2) return node return inner() class Solution: def maxPathSum(self, root: TreeNode) -> tuple[int, list[int]]: self.max_sum = float("-inf") self.best_path = [] def dfs(node: TreeNode) -> tuple[int, list[int]]: if not node: return (0, []) # 递归处理左右子树,获取单侧最大和与对应路径 left_sum, left_path = dfs(node.left) right_sum, right_path = dfs(node.right) # 计算四种可能的路径情况,同时处理子树和为负的情况(直接丢弃该子树) # 1. 仅当前节点 current_only = (node.val, [node.val]) # 2. 当前节点 + 左子树单侧路径(如果左子树和为正) current_left = (node.val + left_sum, [node.val] + left_path) if left_sum > 0 else current_only # 3. 当前节点 + 右子树单侧路径(如果右子树和为正) current_right = (node.val + right_sum, [node.val] + right_path) if right_sum > 0 else current_only # 4. 当前节点作为顶点,连接左右子树的跨路径 cross_sum = node.val + max(left_sum, 0) + max(right_sum, 0) cross_path = (left_path[::-1] if left_sum > 0 else []) + [node.val] + (right_path if right_sum > 0 else []) cross_case = (cross_sum, cross_path) # 更新全局最大和与对应路径 for candidate_sum, candidate_path in [current_only, current_left, current_right, cross_case]: if candidate_sum > self.max_sum: self.max_sum = candidate_sum self.best_path = candidate_path # 返回当前节点向下延伸的最优单侧路径(供父节点使用) return max([current_only, current_left, current_right], key=lambda x: x[0]) dfs(root) return self.max_sum, self.best_path
测试验证
- 用例1:输入
[-10,9,20,None,None,15,7]
输出:(42, [15, 20, 7]),符合预期。 - 用例2:输入
[10,-2,7,8,-4,None,None]
输出:(23, [8, -2, 10, 7]),与预期一致。 - 用例3:输入
[-15,5,6,-8,1,3,9,2,6,None,None,None,None,None,0,None,None,None,None,4,-1,None,None,10,None]
输出:(27, [3, 6, 9, 0, -1, 10]),完全符合预期。
关键改动说明
- 递归函数
dfs返回**(单侧最大和, 对应路径列表)**,确保我们能跟踪实际的节点序列,而不是单纯的数值和。 - 枚举所有可能的路径情况,避免遗漏单侧延伸的长路径或单个节点的最优解。
- 处理子树和为负的情况:如果子树的和小于0,直接丢弃该子树,避免拉低整体路径和。
- 跨左右路径时反转左子树路径:因为左子树的路径是从左子节点向下延伸的,跨路径需要从左子树的最深节点到当前节点再到右子树,所以需要反转左路径。
内容的提问来源于stack exchange,提问作者JJJohn
相关产品推荐
相关产品推荐

