1、深度遍历
考虑到每条路径的节点不一定是从根节点开始的,因此我们需要遍历整棵二叉树分别把每个节点当作是根节点进行处理。我们在进行深度遍历时,利用rootSum遍历单个节点作为根节点时,节点值之和等于targetSum 的路径数目,为此我们在递归时采用temp_path记录路径数。最终我们遍历完所有可能并返回路径数。
class Solution {
public:
int rootSum(TreeNode *root, long targetSum) {
int temp_path = 0;
if (!root) return 0;
if (root->val == targetSum) {
temp_path++;
}
temp_path += rootSum(root->left, targetSum - root->val);
temp_path += rootSum(root->right, targetSum - root->val);
return temp_path;
}
int pathSum(TreeNode *root, long targetSum) {
int pathNum = 0;
if (!root) return pathNum;
pathNum += rootSum(root, targetSum);
pathNum += pathSum(root->left, targetSum);
pathNum += pathSum(root->right, targetSum);
return pathNum;
}
};
2、前缀和
我们在利用深度遍历搜索整棵二叉树时,很多的操作实际上是重复的。为了避免重复的操作,我们可以在以此深度遍历中,利用哈希表来维护我们遍历过路径的前缀和。我们可以利用哈希表来记录在进行深度遍历时,从根节点到某个节点的父节点中所有节点的值的和,对应这样前缀路径的数目。因此当我们在深度遍历整棵树时,我们只需要比较在当前节点的前缀和减去targetSum 后,在当前维护的前缀和哈希表中有多少条这样的路径即可。当我们遍历完这个节点之后的所有节点后,需要从哈希表中减去先前记录的路径从而保证这些前缀和都在同一条路径上。
class Solution {
public:
unordered_map<long long, int> prefix;
int dfs(TreeNode *root, long long curr, int targetSum) {
if (!root) {
return 0;
}
int ret = 0;
curr += root->val;
if (prefix.count(curr - targetSum)) {
ret = prefix[curr - targetSum];
}
prefix[curr]++;
ret += dfs(root->left, curr, targetSum);
ret += dfs(root->right, curr, targetSum);
prefix[curr]--;
return ret;
}
int pathSum(TreeNode* root, int targetSum) {
prefix[0] = 1;
return dfs(root, 0, targetSum);
}
};