題目
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比較,一種方法是用vector保存所有可能路徑傳遞給子樹,即如果當前節點加入到父節點構成的路徑中,則對vector中元素與當前值相加並判斷,如果當前節點不加入,則對當前節點判斷並加入vector當做新的路徑起點,另外一種更高效的方法是記錄到達當前節點的所有路徑和及其出現次數,並且查看減去sum後的值是否出現在記錄中,如果出現,說明在當前節點的路徑中,有一部分的和構成了sum,故出現次數就是減去sum的值出現次數,因爲代表了一共有這麼多的前綴路徑。
方法一:
/**
* 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 comPathSum(TreeNode* root,int sum,vector<int> parentSum,int& res){//利用向量parentSum記錄從父節點向下傳遞的和
for(int i=0;i<parentSum.size();++i){//對於當前節點有兩種選擇,第一對父節點傳遞的值累加,第二從自己開始計算,for循環計算累加過程有多少符合要求的
parentSum[i]+=root->val;
if(parentSum[i]==sum)
++res;
}
parentSum.push_back(root->val);//還有從自身開始計算的
if(root->val==sum)
++res;
if(root->left!=NULL)//遞歸調用左右子樹
comPathSum(root->left,sum,parentSum,res);
if(root->right!=NULL)
comPathSum(root->right,sum,parentSum,res);
}
int pathSum(TreeNode* root, int sum) {
vector<int> parentSum;
if(root==NULL)
return 0;
int res=0;
comPathSum(root,sum,parentSum,res);
return res;
}
};
方法二:
/**
* 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 pathSum(TreeNode* root, int sum) {
unordered_map<int, int> mSum;
mSum[0]++;
int total = 0;
helper(root, 0, sum, total, mSum);//利用mSum保存所有之前經過的路徑和
return total;
}
void helper(TreeNode *p, int cur, int sum, int &total, unordered_map<int, int> &mSum) {
if (!p) return;
cur += p->val;//先對當前節點進行累加
if (mSum.find(cur - sum) != mSum.end()) //不在mSum中尋找sum,而是cur-sum,即前綴和,如果找到了,說明加上當前節點的路徑和-sum的結果是之前路徑中到某個節點的和,即可以尋找到一個和爲sum的路徑,而這樣的路徑個數記錄在mSum中,因此更新路徑個數結果
total += mSum[cur - sum];
mSum[cur]++;//對當前路徑和在mSum中出現的次數進行更新,然後遍歷左右子樹
helper(p->left, cur, sum, total, mSum);
helper(p->right, cur, sum, total, mSum);
mSum[cur]--;//遞歸結束後對當前和的個數減少,因爲向上傳遞後無法再到達當前節點
}
};
參考文章:
C++ solution with prefix sum stored in hash table