LeetCode 437. Path Sum III

437. Path Sum III

Description Submission Solutions

  • Total Accepted: 18367
  • Total Submissions: 47289
  • Difficulty: Easy
  • Contributors: Stomach_ache

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

Subscribe to see which companies asked this question.


【题目分析】
给定一颗二叉树,找到二叉树中从上往下所有的和值为目标值的节点序列。不要求必须从根节点开始到叶子结点。

【思路】
1. 我们可以遍历二叉树的每一个结点,搜索从这个节点出发的所有满足条件的路径的数目。
这种方法以某种顺序遍历一棵树中的所有节点,然后计算从这个节点出发的满足条件的路径数。遍历二叉树的时间复杂度为O(N),对于每一个节点,需要以它为根节点找到所有的符合条件的路径,则综合来看时间复杂度为O(N2)。递归栈的最大深度为logN,因此空间复杂度为O(logN)。
2. So the idea is similar as Two sum, using HashMap to store ( key : the prefix sum, value : how many ways get to this prefix sum) , and whenever reach a node, we check if prefix sum - target exists in hashmap or not, if it does, we added up the ways of prefix sum - target into res.
For instance : in one path we have 1,2,-1,-1,2, then the prefix sum will be: 1, 3, 2, 1, 3, let's say we want to find target sum is 2, then we will have{2}, {1,2,-1}, {2,-1,-1,2} and {2}ways.
这是discuss里的一个比较好的方法,时间复杂度得到了优化。
这个方法的思路是保存从根节点到达当前节点的prefix sum。比如到达当前节点经过的节点val为 1,2,-1,-1,2,那么prefix为1,3,2,1,3. 计算当前节点的prefix sum,然后在前面的所有prefix sum中查找是否存在curSum - target,如果存在,则证明存在这样的点,从这点出发到达当前节点的值正好为target。
 
 
通过上图,我们明白了这个算法的思想。这个算法通过一个hashmap来保存这样的prefix sum信息。那么多二叉树的分叉,是否需要为每一个分支建立一个HashMap呢?我们并不需要这样做,而是采用回溯的做法,如果当前节点的所有的路径都处理完毕了,则把该节点从HashMap中删除,转而去处理别的节点。在初始的时候我们把(0,1)加入HashMap。这是为了那些curSum正好target情况的出现。

【java代码1】
 1 /**
 2  * Definition for a binary tree node.
 3  * public class TreeNode {
 4  *     int val;
 5  *     TreeNode left;
 6  *     TreeNode right;
 7  *     TreeNode(int x) { val = x; }
 8  * }
 9  */
10 public class Solution {
11     public int pathSum(TreeNode root, int sum) {
12         if(root == null) return 0;
13         int res = pathNum(root, sum);
14         
15         if(root.left != null) res += pathSum(root.left, sum);
16         if(root.right != null) res += pathSum(root.right, sum);
17         
18         return res;
19     }
20     
21     public int pathNum(TreeNode root, int sum) {
22         if(root == null) return 0;
23         int res = 0;
24         if(root.val == sum) res++;
25         if(root.left != null) res += pathNum(root.left, sum-root.val);
26         if(root.right != null) res += pathNum(root.right, sum-root.val);
27         
28         return res;
29     }
30 }

 【java代码2】

 1 public class Solution {
 2     public int pathSum(TreeNode root, int sum) {
 3         HashMap<Integer, Integer> preSum = new HashMap<>();
 4         preSum.put(0, 1);
 5         return helper(root, 0, sum, preSum);
 6     }
 7     
 8     public int helper(TreeNode root, int curSum, int target, HashMap<Integer, Integer> preSum) {
 9         if(root == null) return 0;
10         
11         curSum += root.val;
12         int res = preSum.getOrDefault(curSum-target, 0);
13         //把当前节点加入到路径中
14         preSum.put(curSum, preSum.getOrDefault(curSum, 0) + 1);
15         //处理该节点的左子树和右子树
16         res += helper(root.left, curSum, target, preSum);
17         res += helper(root.right, curSum, target, preSum);
18         //回溯。把已经处理完毕的当前节点从路径中清除
19         preSum.put(curSum, preSum.get(curSum) - 1);
20         
21         return res;
22     }
23 }

 

posted @ 2017-02-26 14:10  Black_Knight  阅读(721)  评论(0编辑  收藏  举报