[B003] path tree sum III (recursive | accumulation interval | and prefix)

One, Title Description

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

Second, the problem solution

Method One: recursive

* This title first time when I am most puzzled is:

  • Q1: Why use a multi-layer recursion.
    A1: later discovered at the beginning of the path may not be the root node, may not be the end of the leaf nodes. So we want each node as a beginning to go enumerate each node.

Other and I, II or unchanged.

int cnt;
public int pathSum(TreeNode root, int sum) {
  if (root == null)
      return 0;
  dfs(root, sum);
  pathSum(root.left, sum);
  pathSum(root.right, sum);
  return cnt;
}
void dfs(TreeNode root, int re) {
  if (root == null) {
      return;
  }
  if (re == root.val) {
      cnt++;
  }
  dfs(root.left, re-root.val);
  dfs(root.right, re-root.val);
}

Complexity Analysis

  • time complexity: O ( n 2 ) O (n ^ 2)
  • Space complexity: O ( n ) O (n) ,

Method two: accumulating section

For each node in the path, we are back from the node enumeration to see if there is a path match.

  • Q1: After I can find a path, direct termination cycle?
    A1: counter-example is the root = [0,1,1], sum = 1, the answer is 4.
  • Q2: Why iterate forward from the list?
    A2: Because this combination can guarantee the end of the junction with the previous node.
    • For example: A1 counterexamples, considered a 1, [1, 0] considered a, if at least one front to back will be traversed.
int cnt = 0;
int sum = 0;
List<Integer> path = null;
public int pathSum(TreeNode root, int target) {
  sum = target;
  path = new ArrayList<>();
  dfs(root);
  return cnt;
}
private void dfs(TreeNode root) {
  if (root == null) {
      return;
  }
  path.add(root.val);
  int t = 0;
  for (int i = path.size()-1; i >= 0; i++) {
      t += path.get(i);
      if (t == sum) {
          cnt++;
          //break; 不能提前break [1],[1,0]
      }
  }
  dfs(root.left);
  dfs(root.right);
  path.remove(path.size()-1);
}

Complexity Analysis

  • time complexity: O ( n 2 ) O (n ^ 2)
  • Space complexity: O ( n ) O (n) ,

Method Two: prefix and

If the map there is cur-sum, prove that we began to come from the node cur-sum current node path is a legitimate path. For example: We know that sum = path 11. We went leaf node 3, the sum of the path 21, 21 --11 = 10, there may be a prefix 10 and the map.

Bottom line: If you have a prefix and and cur - sum, but also for current and cur, there must be a difference cur - (cur - sum) path.

      10
     / 
    5
   /
  3  
 / 
3  
int cnt = 0;
int sum = 0;
int cur = 0;
Map<Integer, Integer> map = null;

public int pathSum(TreeNode root, int target) {
   map = new HashMap<>();
   map.put(0, 1);
   sum = target;
   dfs(root);
   return cnt;
}
private void dfs(TreeNode root) {
   if (root == null) {
       return;
   }
   cur += root.val;
   cnt += map.getOrDefault(cur - sum, 0);
   map.put(cur, map.getOrDefault(cur, 0) + 1);
   dfs(root.left);
   dfs(root.right);
   // 回溯
   cur -= root.val;
   map.put(cur, map.get(cur) - 1);
}

Complexity Analysis

  • time complexity: O ( n ) O (n) ,
  • Space complexity: O ( n ) O (n) ,
Published 495 original articles · won praise 105 · views 30000 +

Guess you like

Origin blog.csdn.net/qq_43539599/article/details/104828300