Path Sum III
- 问题描述:给定一颗二叉树,计算有多少条路径的sum等于一个target。路径的定义为从起点和终点之间依次都满足是后者是前者的孩子。如下图所示:

- 问题分析:
- 针对每个节点,我们可以记录从跟节点到该节点所经历的所有value -> paths。
- 然后我们计算该点和前面所有点的value和等于sum的个数。
- 同样的我们递归计算该点的左孩子,右孩子。
- 最终的结果等于cur + left + right
- 是否可以优化?
- 因为我们针对每个点,都要遍历一边paths,path 的长度取决于该点和root之间的距离。
- 我们能否将value记忆起来?来免去这次遍历。
- 我们知道最终的目标是找到一段路径的和为S。那么我们假设从跟节点到当前节点的和为X。则经过包含该点的路径的个数就等于从root遍历到目前这个点有多少和点对应的和为X-S。
- 我们可以用map来记录这些值。map<key, value>, 表示从跟节点开始计算和为key的所有点的个数value。
- 注意,在结束该点的遍历的时候,对应的map的记录也要减去1.
- 代码
#include <vector>
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
class Solution {
public:
unordered_map<int, int> shown;
int exisitSolution(vector<int> paths, int cur_ele, int sum){
int res = 0;
for(int i=paths.size()-1;i>=0;i--){
cur_ele += paths[i];
if(cur_ele == sum)
res += 1;
}
return res;
}
int pathSumCore(TreeNode* root, int sum, vector<int> paths){
if(root == NULL)
return 0;
int cur = exisitSolution(paths, root->val, sum);
if(root->val == sum){
cur += 1;
}
paths.push_back(root->val);
int left = pathSumCore(root->left, sum, paths);
int right = pathSumCore(root->right, sum, paths);
return left + right + cur;
}
int pathSumCoreV2(TreeNode* root, int sum, int pre_sum){
if(root == NULL)
return 0;
pre_sum += root->val;
int cur = shown[pre_sum - sum];
shown[pre_sum] = shown[pre_sum] + 1;
int left = pathSumCoreV2(root->left, sum, pre_sum);
int right = pathSumCoreV2(root->right, sum, pre_sum);
shown[pre_sum] -= 1;
return cur + left + right;
}
int pathSum(TreeNode* root, int sum) {
shown[0] = 1;
return pathSumCoreV2(root, sum, 0);
}
static void solution(){
Solution solution1;
TreeNode* root = TreeNode::buildByLevel({1,0,1,1,2,0,-1,0,1,-1,0,-1,0,1,0}, -5);
TreeNode::levelOrder(root);
cout<<solution1.pathSum(root, 2)<<endl;
}
};