Your are given a binary tree in which each node contains a value. Design an algorithm to get all paths which sum to a given value. The path does not need to start or end at the root or a leaf, but it must go in a straight line down.
Example
Given a binary tree:
1
/ \
2 3
/ /
4 2
for target = 6
, return
[
[2, 4],
[1, 3, 2]
]
1.加减试错递归法。递归定义是从传入的节点出发,把这个点加进备选名单弄出新的链条看看,向根走,试试一路上有没有可能使得sum == target的点。有的话,把这条路加到result里。并且在有这个节点的基础上,再递归看看从该节点的左节点出发走会怎么样,递归看看从该节点的右节点出发走会怎么样。最后删去该节点,避免影响。(前面同时递归了左右节点,不能让左节点保留着影响右节点试走路径)。这种做法主要因为用ArrayList作为buffer试错可以减少空间复杂度。辅助函数头:
private void helper(TreeNode current, int target, int level, List<Integer> buffer, List<List<Integer>> result)
2. 自己一开始做法:遍历嵌套递归。外面遍历每个节点。在每个节点上递归返回所有从这个点出发,随便结束在哪个点但sum == target的。虽然输出正确,但因为嵌套,最后会内存超时的。
1.加减试错递归法
/** * Definition of TreeNode: * public class TreeNode { * public int val; * public TreeNode left, right; * public TreeNode(int val) { * this.val = val; * this.left = this.right = null; * } * } */ public class Solution { /* * @param root: the root of binary tree * @param target: An integer * @return: all valid paths */ public List<List<Integer>> binaryTreePathSum2(TreeNode root, int target) { // write your code here List<List<Integer>> result = new ArrayList<List<Integer>>(); List<Integer> buffer = new ArrayList<Integer>(); helper(root, target, 0, buffer, result); return result; } private void helper(TreeNode root, int target, int level, List<Integer> buffer, List<List<Integer>> result) { if (root == null) { return; } buffer.add(root.val); int sum = 0; for (int i = level; i >= 0; i--) { sum += buffer.get(i); if (sum == target) { List<Integer> list = new ArrayList<Integer>(); for (int j = i; j <= level; j++) { list.add(buffer.get(j)); } result.add(list); } } helper(root.left, target, level + 1, buffer, result); helper(root.right, target, level + 1, buffer, result); // 是size还是length buffer.remove(buffer.size() - 1); } }
2.遍历嵌套递归
/** * Definition of TreeNode: * public class TreeNode { * public int val; * public TreeNode left, right; * public TreeNode(int val) { * this.val = val; * this.left = this.right = null; * } * } */ public class Solution { /* * @param root: the root of binary tree * @param target: An integer * @return: all valid paths */ //??? //感觉复杂度有点高,相当于遍历一次,每个点做一次递归。可行吗? public List<List<Integer>> binaryTreePathSum2(TreeNode root, int target) { // write your code here List<List<Integer>> result = new ArrayList<List<Integer>>(); Stack<TreeNode> stack = new Stack<TreeNode>(); if (root == null) { return result; } stack.push(root); while (!stack.isEmpty()) { TreeNode crt = stack.pop(); List<List<Integer>> paths = helper(crt, target); result.addAll(paths); if (crt.right != null) { stack.push(crt.right); } if (crt.left != null) { stack.push(crt.left); } } return result; } //从该点出发到根部路上所有满足加和为target的路径。 private List<List<Integer>> helper(TreeNode root, int target) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if (root == null) { return result; } if (root.val == target) { List<Integer> newPath = new ArrayList<Integer>(); newPath.add(root.val); result.add(newPath); } List<List<Integer>> left = helper(root.left, target - root.val); List<List<Integer>> right = helper(root.right, target - root.val); for (List<Integer> path : left) { List<Integer> newPath = new ArrayList<Integer>(); newPath.add(root.val); newPath.addAll(path); result.add(newPath); } for (List<Integer> path : right) { List<Integer> newPath = new ArrayList<Integer>(); newPath.add(root.val); newPath.addAll(path); result.add(newPath); } return result; } }