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;
}
};