题目
给定一个二叉树,它的每个结点都存放着一个整数值。找出路径和等于给定数值的路径总数。路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。 二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
思路
一、DFS前缀和加回溯
前缀和:(在树的情况)就是根节点到这个节点的路径和
因为提给要求不一定从根节点开始,所以找一个两节点路径和=target就是这俩节点之间的前缀和之差=target.所以就转换成了找一个节点它的前缀和:sum=presum-tagert.
注意点:
HashMap:来减少运行读取时间,key是前缀和, value是前缀和=key的节点数量
回溯:因为题目定义方向向下,所以只有同一条路径上的节点间(节点和其某一祖先节点间)的前缀和做差才有意义。所以当前节点处理完之后,需要从map中移除这一个前缀和,然后再进入下一个分支路径。 回溯就是在出递归之后做操作(撤销/移除选择)来维护递归有效性.
// 定义一个全局变量来储存路径和=target的数量
int res = 0;
public int pathSum(TreeNode root, int targetSum) {
// 创建HasMap来储存路径和
HashMap<Integer,Integer> map = new HashMap<>();
// 放入0,1是因为要有一个0值作为起点,便于后续路径和计算(节点值-0)
map.put(0,1);
DFS(root,targetSum,map,0);
// return DFS(root,targetSum,map,0);
return res;
}
// 实现功能是计算节点前缀和、同时放入map中,返回值为前缀和的值。在过程中求得路径和
public int DFS(TreeNode root, int targetSum,HashMap<Integer,Integer> map,int sum ){
if(root==null){
return 0;
}
// 求前缀和
sum += root.val;
// 从map中读取前缀和为sum-targetSum的节点数量,用res记录。
res += map.getOrDefault(sum-targetSum,0);
// 将这个节点前缀和放入对应key的统计部分
map.put(sum,map.getOrDefault(sum,0)+1);
// res += DFS(root.left,targetSum,map,sum);
// res += DFS(root.right,targetSum,map,sum);
// 遍历左右节点
DFS(root.left,targetSum,map,sum);
DFS(root.right,targetSum,map,sum);
// 重点:因为题目规定路径方向向下,所以节点和其某一祖先节点间的前缀和做差才有意义,所以当前节点都处理完之后,要将它移除。
map.put(sum,map.get(sum)-1);
return sum;
}
}
二、双递归
这种题目需要从每个节点开始进行类似的计算,所以第一个递归用来遍历这些节点,这二个递归用来处理这些节点,进行深度优先搜索。
class Solution {
int pathnumber;
//遍历节点
public int pathSum(TreeNode root, int sum) {
if(root == null) return 0;
Sum(root,sum);
pathSum(root.left,sum);
pathSum(root.right,sum);
return pathnumber;
}
//处理节点
public void Sum(TreeNode root, int sum){
if(root == null) return;
sum-=root.val;
if(sum == 0){
pathnumber++;
}
Sum(root.left,sum);
Sum(root.right,sum);
}
}`
时间复杂度很高,在计算SUM的时候也计算了下面,优化可以把左右子树拿出来。
int pathnumber;
public int pathSum(TreeNode root, int sum) {
if(root == null) return 0;
Sum(root,sum);
}
public int path(TreeNode root, int sum){
pathSum(root.left,sum);
pathSum(root.right,sum);
return pathnumber;
}
public void Sum(TreeNode root, int sum){
if(root == null) return;
sum-=root.val;
if(sum == 0){
pathnumber++;
}
Sum(root.left,sum);
Sum(root.right,sum);
}
}