Path Sum III Leetcode
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
这道题我以为很难呢,结果很顺利就写出来了。。。就是时间空间复杂度高了点。。。= =但是训练还是有成效的吧是吧。。。。只不过这两天都没刷题心里很惭愧啊。
同样,还是采用自顶向下的方法
public class Solution { private int pathSum = 0; public int pathSum(TreeNode root, int sum) { List<Integer> l = new ArrayList<>(); helper(root, l, sum); return pathSum; } public void helper(TreeNode root, List<Integer> subSum, int sum) { if (root == null) { return; } if (root.val == sum) { pathSum++; } int size = subSum.size(); for (int i = 0; i < size; i++) { if (subSum.get(i) - root.val == 0) { pathSum++; } subSum.set(i, subSum.get(i) - root.val); } subSum.add(sum - root.val); helper(root.left, new ArrayList<>(subSum), sum); helper(root.right, new ArrayList<>(subSum), sum); } }
看了下top solution的方法,还是人家的好。。。我就没有结合起来two sum的方法,只结合了树的方法,大概是我当时two sum就不怎么熟练。。。还是要自己完全独立写出来才是自己的啊。。。另外要学会把树看成线性的来思考。
public class Solution { private int count = 0; public int pathSum(TreeNode root, int sum) { Map<Integer, Integer> preSum = new HashMap<>(); preSum.put(0, 1); helper(root, sum, 0, preSum); return count; } public void helper(TreeNode root, int target, int currSum, Map<Integer, Integer> preSum) { if (root == null) { return; } currSum += root.val; if (preSum.containsKey(currSum - target)) { count += preSum.get(currSum - target); } if (preSum.containsKey(currSum)) { preSum.put(currSum, preSum.get(currSum) + 1); } else { preSum.put(currSum, 1); } helper(root.left, target, currSum, preSum); helper(root.right, target, currSum, preSum); preSum.put(currSum, preSum.get(currSum) - 1); } }
这个方法采用了two sum的思想,一直加和,如果presum - target在map里面,说明这一段的总和是target。但要注意最后一句,防止[1, -2, -3]演变成线性-2, 1, 3,要在左右都跑完之后去掉本节点对这个节点所在的根的右边节点的影响。
这个代码可以改进,map的getOrDefault的方法可以记一下。这个题目挺巧妙的,以后回顾一下。
public class Solution { public int pathSum(TreeNode root, int sum) { Map<Integer, Integer> preSum = new HashMap<>(); preSum.put(0, 1); int count = helper(root, sum, 0, preSum); return count; } public int helper(TreeNode root, int target, int currSum, Map<Integer, Integer> preSum) { if (root == null) { return 0; } currSum += root.val; int count = preSum.getOrDefault(currSum - target, 0); preSum.put(currSum, preSum.getOrDefault(currSum, 0) + 1); count += helper(root.left, target, currSum, preSum) + helper(root.right, target, currSum, preSum); preSum.put(currSum, preSum.get(currSum) - 1); return count; } }
注意getOrDefault里面一定要是key,不可以在里面做运算,要做到括号外面做。