[leetcode] Path Sum III

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.
  • 代碼
//
// Created by Liang on 2019-07-07.
//
#include <vector>
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
class Solution {
public:
    unordered_map<int, int> shown; // 判斷路徑上從root到某點的sum是否出現過
    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){
        // 必須包含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; // 包含當前節點從root到當前節點的sum
        int cur = shown[pre_sum - sum]; // 存在某種節點的個數,從根節點到該節點的和爲pre_sum - sum, 則從當前節點到該節點的和就爲sum
        shown[pre_sum] = shown[pre_sum] + 1; // 和爲pre sum的節點個數加一
        int left = pathSumCoreV2(root->left, sum, pre_sum);
        int right = pathSumCoreV2(root->right, sum, pre_sum);
        shown[pre_sum] -= 1;    // 因爲只能是單邊的,所以這裏需要減1
        return cur + left + right;
    }
    int pathSum(TreeNode* root, int sum) {
        shown[0] = 1;
        return pathSumCoreV2(root, sum, 0);
//        vector<int> paths;
//        if(root == NULL)
//            return 0;
//        paths.push_back(root->val);
//        int cur = (root->val == sum);
//        int left = pathSumCore(root->left, sum, paths);
//        int right = pathSumCore(root->right, sum, paths);
//        return left + right + cur;
    }
    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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章