解这道题的思路有两种:
- 固定根节点,找子树中满足的所有路径(时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( n ) O(n) O(n))
- 前缀和思想,固定路径的终点,向上找到父节点中满足的路径(时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n))
第一种思路其实就是暴力。用两个递归,没有特别的技巧。
第二种思路中,不断记录从根节点到当前节点的路径和,存储到map中便于快速查找。
这样,每遇到新的节点,只需要查找父节点中路径和为current-target
的值的个数即可。
注意:
map中仅存储和维护父节点的路径和,在当前节点计算完成返回时,要将map中当前节点的路径和删除
同时,map中仅存储父节点的信息,因此要先计算当前节点的路径数量,再将current
路径和加入map,进行子树的计算
附上代码:
前缀和
typedef long long ll;
class Solution {
map<ll, int> prefix;
public:
int dfs(TreeNode* node, int target, ll current) {
if(!node) return 0;
int out = 0;
current += node->val;
if(prefix.count(current-target) > 0) out += prefix[current - target];
prefix[current]++;
out += dfs(node->left, target, current);
out += dfs(node->right, target, current);
prefix[current]--;
return out;
}
int pathSum(TreeNode* root, int targetSum) {
prefix[0] = 1;
return dfs(root, targetSum, 0);
}
};
递归固定根节点
class Solution {
public:
int dfs(TreeNode* node, int target) {
if(!node) return 0;
int out = 0;
if(node->val == target) out++;
out += dfs(node->left, target - node->val);
out += dfs(node->right, target - node->val);
return out;
}
int pathSum(TreeNode* root, int targetSum) {
if(!root) return 0;
int total = 0;
total += dfs(root, targetSum);
total += pathSum(root->left, targetSum);
total += pathSum(root->right, targetSum);
return total;
}
};