题目描述
给定一个二叉树的根节点 root
,和一个整数 targetSum
,求该二叉树里节点值之和等于 targetSum
的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
示例
示例 1:
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。
示例 2:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3
提示:
-
- 二叉树的节点个数的范围是
[0,1000]
-109 <= Node.val <= 109
-1000 <= targetSum <= 1000
- 二叉树的节点个数的范围是
题解
方法1:深度优先搜索
穷举所有的可能,我们访问每一个节点 node,检测以 node 为起始节点且向下延深的路径有多少种。我们递归遍历每一个节点的所有可能的路径,然后将这些路径数目加起来即为返回结果。
go代码
//采用递归遍历二叉树的每个节点,求每个节点的rootsum,然后将每个节点所有求的值进行相加求和返回
func pathSum(root *TreeNode, targetSum int) int {
if root == nil {
return 0
}
//fmt.Println("root: "+strconv.Itoa(root.Val))
//以当前节点为根节点,获取该节点的rootSum
sum := rootSum(root, targetSum)
//递归向下,将当前节点的左孩子节点设为根节点,获取该节点的rootSum
sum += pathSum(root.Left, targetSum)
//递归向下,将当前节点的右孩子节点设为根节点,获取该节点的rootSum
sum += pathSum(root.Right, targetSum)
return sum
}
//递归搜索,返回从当前节点向下进行深度优先搜索,节点累加等于targetSum的路径数
func rootSum(root *TreeNode, targetSum int) int {
if root == nil {
return 0
}
sum := 0
if root.Val == targetSum {
sum++
}
// fmt.Println("root: "+strconv.Itoa(root.Val)+" targetSum: "+strconv.Itoa(targetSum))
sum += rootSum(root.Left, targetSum-root.Val)
sum += rootSum(root.Right, targetSum-root.Val)
return sum
}
方法2: 前缀和
解法一中应该存在许多重复计算。我们定义节点的前缀和为:由根结点到当前结点的路径上所有节点的和。我们利用先序遍历二叉树,记录下根节点 root 到当前节点 p 的路径上除当前节点以外所有节点的前缀和,在已保存的路径前缀和中查找是否存在前缀和刚好等于当前节点到根节点的前缀和 curr 减去 targetSum。
go代码:
func pathSum(root *TreeNode, targetSum int) (ans int) {
// 定义用于存储前缀和的map,key是和,val指是否存在,val为0,指没有和为key的路径,val为1指有和为key的路径
preSum := map[int64]int{0: 1}
// 定义匿名函数
var dfs func(*TreeNode, int64)
// 用于递归遍历所有节点,并计算每个节点到根节点之间,和为targetSum的路径总数
dfs = func(node *TreeNode, curr int64) {
if node == nil {
return
}
//计算根节点到当前节点的路径总和curr
curr += int64(node.Val)
// 获取在记录路径前缀和的map中,路径和为curr-targetSum的路径总数
// 如根节点到pi的路径和为n,n=curr-targetSum,即n+targetSum=curr,那pi+1到当前节点的路径和就是targetSum,那路径和为curr-targetSum,也就是n的路径总数,就是当前节点到根节点之间,和为targetSum的路径总数
ans += preSum[curr-int64(targetSum)]// 从根节点到当前节点总和为curr的路径数+1
preSum[curr]++
dfs(node.Left, curr)
dfs(node.Right, curr)
preSum[curr]--
return
}
dfs(root, 0)
return
}