这是树的第15篇算法,力扣链接。
给你二叉树的根节点
root
和一个表示目标和的整数targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和targetSum
。如果存在,返回true
;否则,返回false
。叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22 输出:true 解释:等于目标和的根节点到叶节点路径如上图所示。
这道题听起来是标准的前序遍历的做法,回忆一下前序遍历:
前序遍历 (Preorder Traversal)
在前序遍历中,节点的访问顺序如下:
- 访问根节点
- 遍历左子树
- 遍历右子树
前序遍历通常用于创建树的副本。当你访问节点之后立即复制节点,你可以通过前序遍历复制所有节点并创建一棵相同的树。
例子
假设有一棵二叉树如下:
A / \ B C / \ \ D E F
- 前序遍历:
A, B, D, E, C, F
。首先访问根节点(A),然后是左子树(B, D, E),最后是右子树(C, F)。
解题如下:
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}
stack := []*TreeNode{root}
sums := []int{root.Val}
for len(stack) > 0 {
node := stack[len(stack)-1]
currentSum := sums[len(sums)-1]
stack = stack[:len(stack)-1]
sums = sums[:len(sums)-1]
if node.Left == nil && node.Right == nil && currentSum == targetSum {
return true
}
if node.Left != nil {
stack = append(stack, node.Left)
sums = append(sums, currentSum+node.Left.Val)
}
if node.Right != nil {
stack = append(stack, node.Right)
sums = append(sums, currentSum+node.Right.Val)
}
}
return false
}
注意一下遇到的几个坑:
if node.Left == nil && node.Right == nil && currentSum == targetSum { return true }
这个代码是避免测试用例root = [1,2] 这种场景,因为题目要求是到子叶的路径总和,这里1的值并不是子叶的路径而是根节点的路径,只有当左右子叶为空的时候根节点才能当做子叶。
然后是这里的sums要跟着左右节点一同入栈,这样就能动态的取出当前的路径和。
当然,也可以递归的方式解题:
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}
if root.Left == nil && root.Right == nil {
return targetSum == root.Val
}
return hasPathSum(root.Left, targetSum-root.Val) || hasPathSum(root.Right, targetSum-root.Val)
}
除了前序遍历,还有广度优先遍历的方式求路径和。
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}
queue := []*TreeNode{root}
sum := []int{root.Val}
for len(queue) != 0 {
node := queue[0]
queue = queue[1:]
currentSum := sum[0]
sum = sum[1:]
if node.Left == nil && node.Right == nil {
if currentSum == targetSum {
return true
}
continue
}
if node.Left != nil {
queue = append(queue, node.Left)
sum = append(sum, node.Left.Val+currentSum)
}
if node.Right != nil {
queue = append(queue, node.Right)
sum = append(sum, node.Right.Val+currentSum)
}
}
return false
}
写法相似,但是遍历的顺序其实不一样。