给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
解题思路如下:
为了判断是否存在这样的一条路径,代码需要采用递归和回溯的方式进行树的遍历。具体步骤如下:
-
递归遍历每个节点:从根节点开始,逐步向下遍历二叉树的每个节点。在遍历过程中,不断更新当前路径的节点值之和,判断是否能够达到目标和。
-
递归终止条件:递归的终止条件有两个:
- 当遍历到一个叶子节点时,如果当前路径的节点值之和等于目标和,则返回
True
,表示找到了这样的一条路径。但这样代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。 - 如果遍历到叶子节点但未达到目标和,或者当前节点的左右子树都没有满足条件的路径,则返回
False
。
- 当遍历到一个叶子节点时,如果当前路径的节点值之和等于目标和,则返回
-
回溯:如果当前节点的左右子树都没有找到满足条件的路径,那么需要回溯,即撤销对当前节点的处理,并继续探索其他可能的路径。
完整代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def traversal(self, cur: TreeNode, count: int) -> bool:
if not cur.left and not cur.right and count == 0: # 遇到叶子节点,并且计数为0
return True
if not cur.left and not cur.right: # 遇到叶子节点直接返回
return False
if cur.left: # 左
count -= cur.left.val
if self.traversal(cur.left, count): # 递归,处理节点
return True
count += cur.left.val # 回溯,撤销处理结果
if cur.right: # 右
count -= cur.right.val
if self.traversal(cur.right, count): # 递归,处理节点
return True
count += cur.right.val # 回溯,撤销处理结果
return False
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
if root is None:
return False
return self.traversal(root, sum - root.val)
首先,检查当前节点是否是叶子节点(即没有左子节点和右子节点),并且剩余目标和为零。如果条件满足,则返回 True
,表示找到了满足条件的路径。如果当前节点是叶子节点,但剩余目标和不为零,则返回 False
,表示这条路径不满足条件。
if cur.left:
count -= cur.left.val
if self.traversal(cur.left, count):
return True
count += cur.left.val
如果当前节点有左子节点,则执行以下步骤:
- 从count中减去左子节点的值。
- 递归调用traversal方法,传入左子节点和新的count值。
- 如果递归调用返回
True
,则直接返回True
,表示找到了满足条件的路径。 - 如果递归调用返回
False
,则将count的值加回来,进行回溯,撤销之前的计算。
右子节点同理。如果当前节点的左右子节点都不存在满足条件的路径,则返回 False
。
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
if root is None:
return False
return self.traversal(root, sum - root.val)
检查根节点是否为空。如果为空,则返回 False
,表示不存在任何路径。调用 traversal
方法,传入根节点和 sum - root.val
作为参数。sum - root.val
表示从目标和中减去根节点的值,剩下的值将作为新的目标和传递给 traversal
方法。