437. Path Sum III ●●

437. Path Sum III ●●

describe

Given the root node root of a binary tree and an integer targetSum, find the number of paths whose sum of node values ​​in the binary tree is equal to targetSum.

The path does not need to start from the root node, nor does it need to end at the leaf node, but the path direction must be downward (only from parent node to child node).

example

insert image description here
Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
Output: 3
Explanation: There are 3 paths with the sum equal to 8, as shown in the figure Show.

answer

1. Divide and conquer + depth-first search DFS

For each node, calculate the number of paths starting from this node.
Node values ​​can be positive or negative, so the recursion ends at the leaf node.

  • Time complexity: O ( N 2 ) O(N^2)O ( N2 ), where N is the number of nodes in the binary tree. For each node, when calculating the number of paths starting from this node, it is necessary to traverse all nodes of the subtree rooted at this node, so the maximum time spent on finding the path is O(N), we will Each node calculates the number of paths starting from this node, so the time complexity isO ( N 2 ) O(N^{2})O ( N2)
  • Space complexity: O(N), considering that recursion needs to open up space on the stack.
class Solution {
    
    
public:
    int rootSum(TreeNode* node, long long target){
    
     
        if(!node) return 0;
        int count = 0;
        if(target == node->val) ++count;    // 当前节点满足条件,计数+1,并继续往下查找
        count += rootSum(node->left, target-node->val) + rootSum(node->right, target-node->val);
        return count;
        // return (target == node->val) 
        //        + rootSum(node->left, target-node->val) 
        //        + rootSum(node->right, target-node->val);
    }  
    
    int pathSum(TreeNode* root, int targetSum) {
    
    
        if(!root) return 0;
        int ans = 0;                            // 分治
        ans += rootSum(root, targetSum);        // 以root为起点,查找以该节点为路径开头,且和为targetSum的路径数量
        ans += pathSum(root->left, targetSum);  // 以root->left为根的子树中,和为targetSum的路径数量
        ans += pathSum(root->right, targetSum); // 以root->right为根的子树中,查找和为targetSum的路径数量
        return ans;
    }
};

2. Prefix and

There should be many double calculations in solution one.

We define the prefix sum of a node as: the sum of all nodes on the path from the root node to the current node.

We use the pre-order traversal of the binary tree to record the prefix sum of all nodes except the current node on the path from the root node root to the current node node, and find out whether there is a prefix sum in the saved path prefix sum that is just equal to the current node to the root node. Prefix sum curr minus targetSum , if present, indicates that there are paths from intermediate nodes to node node (end) and the sum is targetSum , and the number of these paths is given by preCnt prefix and hash table.

Notice:

  1. For the empty path, we also need to save and pre-process it. At this time, because the empty path does not pass through any nodes, its prefix sum is 0, that ispreCnt[0] = 1;
  2. When exiting the path of the current node , it is necessary to pay attention to updating the number of corresponding prefix sums in the hash table.
  3. Using depth-first search, compute the sum of eligible paths ending at each node .
  • Time complexity: O(N), where N is the number of nodes in the binary tree. Using the prefix sum only needs to traverse the binary tree once.
  • Space complexity: O(N).
class Solution {
    
    
public:
    unordered_map<long long, int> preCnt;       // <路径和, 个数>
    
    int dfs(TreeNode* node, long long curr, int target){
    
    
        if(node == nullptr) return 0;
        int cnt = 0;
        curr += node->val;                      // curr 为根节点到 node 节点的路径和,存在curr-target表示存在中间节点到node节点的路径和为target
        if(preCnt.count(curr-target)){
    
              // 以node节点结尾的路径和为target的数量
            cnt += preCnt[curr-target];
        }
        
        ++preCnt[curr];                         // 哈希记录路径和
        cnt += dfs(node->left, curr, target);   // 以node->left结尾的路径和为target的数量
        cnt += dfs(node->right, curr, target);  // 以node->eight结尾的路径和为target的数量
        --preCnt[curr];                         // 退出当前节点,回溯
        return cnt;
    }
    
    int pathSum(TreeNode* root, int targetSum) {
    
    
        preCnt[0] = 1;                      // 有一条空路径,和为0
        return dfs(root, 0, targetSum);
    }
};

Guess you like

Origin blog.csdn.net/qq_19887221/article/details/126053590