题目
给定一个二叉树的根节点 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
链接
dfs暴搜
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
// 先序遍历整棵二叉树,同时递归调用dfs统计每个节点为根的二叉树路径数
int pathSum(TreeNode* root, int targetSum) {
if(!root) return 0;
int res = dfs(root, targetSum);
res += pathSum(root->left, targetSum);
res += pathSum(root->right, targetSum);
return res;
}
// 用值减少的方式求目标值
int dfs(TreeNode*root, long targetSum){
if(!root) return 0;
int res = 0;
if(targetSum == root->val) res++;//求路径和时,这里不用return,因为在次路径基础上后面可能继续走还有节点构成的路径符合条件
res += dfs(root->left, targetSum - root->val);
res += dfs(root->right, targetSum - root->val);
return res;
}
};
前缀和+hash表优化
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<long, int> hash;
int ans;
int pathSum(TreeNode* root, int targetSum) {
hash[0]++;//当sum[i]刚好等于targetSum时,符合条件
dfs(root, 0, targetSum);//先序遍历,构造前缀和
return ans;//返回结果
}
void dfs(TreeNode * root, long curSum, int targetSum){
if(!root) return;
curSum += root->val;//累加前缀和
ans += hash[curSum - targetSum];//统计前面的路径中出现了多少次能够成目标值的前缀数组sum[j]
hash[curSum]++;//把sum[i]存储到hash表中,注意上下两行代码的顺序
dfs(root->left, curSum, targetSum);//继续遍历左子树
dfs(root->right, curSum, targetSum);//继续遍历右子树
hash[curSum]--;//删掉当前先序遍历的节点构成的前缀和curSum出现的次数
}
};