Leetcode 437 Path Sum III
题目原文
You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go downwards(traveling only from parent nodes to child nodes).
The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.
Example:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ \ \
3 2 11
/ \ \
3 -2 1
Return 3. The paths that sum to 8 are:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
题意分析
在一棵二叉树上找和为sum的path,path必须是从上到下连续的一条,但起始和终止不一定要在root或leaf。求满足条件的path数。
解法分析
本题采用两种思路:
- 深度优先搜索
本题的深度优先搜索思路类似于560 Subarray Sum,在深度优先的一条路上,每遇到一个节点,就将val加到sum中,并用一个unordered_map存储sum,以及sum出现的次数(算法中这一步要最后进行),将sum-target,得到的值作为key进入map搜索是否存在,如果存在,就说明累加和为sum-target的节点到本节点的中间path和为target,这样的path的个数为map[sum-target],并将该值加到全局变量count中。最后将sum放入map中,如果存在就将value加一。之后就递归搜索两个子节点,map通过传引用的方式传给下一层dfs,这样能大大节省时间开销,在两个dfs返回后,需要将map[sum]--,而对于sum来说,它是值传递,不改变原值。C++代码如下:
/**
* 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 {
private:
int pcount;
int target;
public:
void dfsSum(TreeNode* root,int sum,unordered_map<int,int> &smap){//use the &smap to reduce time
if(root==NULL)
return;
sum+=root->val;
if(smap.count(sum-target))
pcount+=smap[sum-target];
smap[sum]++;//must behind the above sentence
dfsSum(root->left,sum,smap);
dfsSum(root->right,sum,smap);
smap[sum]--;//smap is a &
}
int pathSum(TreeNode* root, int sum) {
pcount=0;
int pSum=0;
target=sum;
unordered_map<int,int> smap;//first is the sum, second is the path that sum to this sum from the root
smap[0]=1;
dfsSum(root,pSum,smap);
return pcount;
}
};
- 递归思想
递归思想就将大问题分解为小问题递归解决,总的问题为以root为根的数的path数,可以分解为三部分,第一部分为path包含root的path数,第二部分为path不包含root,左子树的path数,第三部分为path不包含root,右子树的path数。C++代码如下:
class Solution {
public:
int containSum(TreeNode* root,int sum){//the path contains root and sums to sum
if(root==NULL)
return 0;
if(root->val==sum)
return 1+containSum(root->left,sum-root->val)+containSum(root->right,sum-root->val);
return containSum(root->left,sum-root->val)+containSum(root->right,sum-root->val);
}
int pathSum(TreeNode* root, int sum) {
if(root==NULL)
return 0;
return pathSum(root->left,sum)+pathSum(root->right,sum)+containSum(root,sum);
}
};
注意containSum的结束条件,root->val==sum,此时的返回值还需继续向下递归,只是多加了1,因为val可能有负数,后面还有可能达到target。