437.路径总和III
问题:给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
示例:
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3
思路:
- dfs暴力求解
class Solution {
private int res;
private int target;
public int pathSum(TreeNode root, int targetSum) {
res = 0;
this.target = targetSum;
dfs(root);
return res;
}
private void dfs(TreeNode node){
if(node == null){
return;
}
check(node, target);
dfs(node.left);
dfs(node.right);
}
private void check(TreeNode node, int target){
if(node == null){
return ;
}
int tar = target - node.val;
if(tar == 0){
res++;
}
check(node.left, tar);
check(node.right, tar);
}
}
- 回溯+前缀和+dfs
类似于求和为targetSum的子数组的个数,将从根节点到当前节点前序遍历的结果看作为一个数组,然后利用前缀和求和为targetSum的子数组的个数,并使用哈希表来记录前缀和 方便计算结果。这个数组是不断变化的,因为路径方向必须是向下的,所以dfs时 离开节点的时候必须将当前路径和在哈希表中删掉,防止影响其他节点。
class Solution {
private int pathSum, targetSum;
private int res;
//记录从根节点到当前节点的路径和为pathSum 的路径个数
private HashMap<Integer, Integer> map;
public int pathSum(TreeNode root, int targetSum) {
if(root == null){
return 0;
}
this.res = 0;
this.targetSum = targetSum;
this.pathSum = 0;
this.map = new HashMap();
//保证从根节点开始的合法路径 被纳入结果
//比如[1, 4] targetSum = 5 如果不加这个初始化 则会返回0
map.put(0, 1);
dfs(root);
return res;
}
private void dfs(TreeNode node){
if(node == null){
return;
}
//前缀和
pathSum += node.val;
//从二叉树的根节点开始,路径和为 pathSum - targetSum 的路径条数
//相当于求从根节点到当前节点的路径中 路径和为targetSum的路径个数(不一定是从根节点开始的路径)
res += map.getOrDefault(pathSum - targetSum, 0);
//记录从二叉树的根节点到当前节点的路径中,路径和为 pathSum 的路径条数
map.put(pathSum, map.getOrDefault(pathSum, 0) + 1);
dfs(node.left);
dfs(node.right);
//因为我们需要的路径只能是从父节点到子节点的路径
//所以离开这个节点的时候,需要将这个节点的相关信息删掉
//以免影响其他节点的计算 回溯的思想
map.put(pathSum, map.get(pathSum) - 1);
pathSum -= node.val;
}
}
整理思路,记录博客,以便复习。若有误,望指正~