题目描述:
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
返回 3。和等于 8 的路径有:
- 5 -> 3
- 5 -> 2 -> 1
- -3 -> 11
方法1:使用两个递归
主要思路:
(1)使用两个递归,第一个递归用于统计以各个当前结点为根节点,使用初始值sum,来统计各个子树的路径数量;
(2)第二个递归用于统计给定的子树下,统计各个子树的满足要求的路径所使用的递归;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int helper(TreeNode* root,int sum){
//终止条件
if(root==NULL)
return 0;
sum-=root->val;
int res=sum==0?1:0;//满足要求的一条部分路径
return res+helper(root->left,sum)+helper(root->right,sum);//接着递归统计
}
//递归函数1
int pathSum(TreeNode* root, int sum) {
if(root==NULL)
return 0;
int result=helper(root,sum);//统计当前结点下新的树的满足要求的路径的数量
//以左右结点为新根节点,递归重新统计各个可能的作为子树的结果
int l_num=pathSum(root->left,sum);
int r_num=pathSum(root->right,sum);
return result+l_num+r_num;//将三个结果返回
}
};
方法2:递归,回溯,前缀和
主要思路:
(1)前缀和是统计到当前结点时,之前的路径中出现的所有值之和(和积分图像有点像),这样,通过当前的前缀和减去之前的某个位置的前缀和,就能够得到之前位置到当前位置之间的所有元素之和;
(2)利用前缀和的概念,可以将路径上的各个结点出的前缀和统计起来,使用unordered_map进行存储,统计某个前缀和的出现次数;
(3)然后,使用当前前缀和减去需要获得路径和sum,得到的值若是在unordered_map中出现过,则说明存在路径,加上相应的路径数量,若是没有,则说明没有组成需要的路径,然后将当前前缀和加入到unordered_map中;
(4)由于路径时递归的,且存储的是当前的路径,故需要进行回溯,去除要成为“之前路径“中的结点;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void helper(TreeNode* root,int& sum,unordered_map<int,int>& mp,int& count,int step){
if(root==NULL)//终止
return;
step+=root->val;//当前前缀和
if(mp.count(step-sum))//若减去sum后的前缀存在,则说明可以存在符合要求的路径
count+=mp[step-sum];
++mp[step];//将当前前缀和加入到结果中
//递归
helper(root->left,sum,mp,count,step);
helper(root->right,sum,mp,count,step);
//回溯
--mp[step];
if(mp[step]==0)
mp.erase(step);
}
int pathSum(TreeNode* root, int sum) {
unordered_map<int,int>mp;//存储前缀和
mp[0]=1;//初始值
int count=0;//统计满足要求的路径的数量
int step=0;//统计当前路径和,名字没取好
helper(root,sum,mp,count,step);
return count;
}
};