1、数据结构
2、回溯:看到二叉树,要计算满足条件的路径个数的时候,首先就想到了回溯。为了理清回溯的整体思路,思考暴力穷举的情况下如何遍历所有路径和。
暴力穷举:从每一个节点出发,计算当前节点到各个子树节点所有路径,按照路径长度进行遍历。
重复的计算:会对子树的路径和进行重复计算。例如,对于题目途中10的节点,长为3的路径包含以下几种情况 [10,5,3][10,5,2][10,-3,11],这其中包含了节点5,-3对应的长为2的路径。
根据暴力穷举的思路构建递归思路:
1)维护如下公共变量:res(int)记录满足条件的路径数
2)回溯过程,对二叉树进行层序遍历,传递如下参数
(1)当前树的根节点:*TreeNode
(2)当前根节点的父节点到当前节点的路径和:fathers map[*TreeNode]int 类型
3)遍历到一个树节点:判断当前节点值是否==targetSum
(1)是:res++
(2)否:res不做改变
(3)不论是否:遍历fathers,对应的路径和依次相加,判断结果是否==targetSum,同时用相加的新sum更新原有sum,是的话res++
(4)之后将当前节点添加到fathers中,判断左右节点是否为空,不为空的进行递归,传入参数为非空子节点以及更新后的fathers哈希表
注意:在传递map等内容的时候,注意指针类型的修改会跨函数保留
Go:基本也算暴力穷举,最后的通过结果可太差了
func pathSum(root *TreeNode, targetSum int) int {
var res int=0
var seq func(r *TreeNode, s map[*TreeNode]int)
seq=func(r *TreeNode, s map[*TreeNode]int){
if r==nil{ return }
// fmt.Println(r.Val, s, res)
var sumMap map[*TreeNode]int=make(map[*TreeNode]int)
if r.Val==targetSum{ res++ }
for k, v:=range s{
if r.Val+v==targetSum{ res++ }
sumMap[k]=r.Val+v
}
sumMap[r]=r.Val
seq(r.Left, sumMap)
seq(r.Right, sumMap)
}
seq(root, make(map[*TreeNode]int))
return res
}
考虑如何降低时空复杂度
1)在遍历的过程中进行剪枝操作,但是因为二叉树中各个节点的值可能为负数,即使当前路径和>targetSum,后续相加后依然有可能==targetSum
2)使用共有空间,记录已经遍历过的父辈路径和