1. 问题描述:
给定一个二叉树,它的每个结点都存放着一个整数值。找出路径和等于给定数值的路径总数。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
返回 3。和等于 8 的路径有:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum-iii
2. 思路分析:
这道题目是一维情况下的扩展,一维的时候是给出n个整数序列,求解总和为t的区间个数,在二维的时候我们是在二叉树上统计总和为t的路径数目,其实二维的时候与一维也是类似的,我们也可以使用同样的思路解决,也即使用前缀和 + 哈希表的思路解决,我们可以把每一条路径看成是一个整数序列,这样就可以将所有的路径看成是一维的情况(从根节点往下的路径看成是一维数组),在遍历二叉树节点的时候维护到当前节点的前缀和即可,并且使用哈希表记录一下到当前节点之前的前缀和,在往下递归之前判断是否存在从根节点往下的节点,使得该节点到当前遍历节点的路径总和为t(其实就是看一下是否存在这样的区间),我们在递归完当前节点返回到当前节点的时候那么需要回溯,也即删除掉从根节点到当前节点哈希表的前缀和,尝试下一条路径对应的区间。与一维的思路是一样的,只是遍历每一条路径的时候看成是一维的情况。
3. 代码如下:
import collections
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
res = 0
# t为要找到的目标值
def dfs(self, root: TreeNode, t: int, dic: collections.defaultdict, s: int):
if not root: return
# 计算从根节点到当前节点的前缀和
s += root.val
# 寻找以当前节点为右端点以之前的节点为左端点是否存在左端点j使得[j, i] = t
if dic[s - t] > 0: self.res += dic[s - t]
# 更新字典中的前缀和与之前一维的情况是类似的
dic[s] += 1
self.dfs(root.left, t, dic, s)
self.dfs(root.right, t, dic, s)
# 回溯的时候删除掉到当前路径的前缀和
dic[s] -= 1
# 其实与之前一维的版本是类似的, 只是这里需要在dfs搜索的过程中维护前缀和, 每一条路径可以看成
# 是一维的情况
def pathSum(self, root: TreeNode, targetSum: int) -> int:
dic = collections.defaultdict(int)
# 初始节点, 边界情况
dic[0] = 1
self.dfs(root, targetSum, dic, 0)
return self.res