题目来源:力扣
题目描述:
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
审题:
该题目为树搜索中的路径和问题.本题的复杂之处在于不单单是搜索符合要求的路径数量,而且是要打印出路径.本题的简单之处则在于对路径的定义:路径从根节点开始,且结束于叶节点.
考虑我们该如何打印出节点的路径呢?对于这道题,我一开始的设计是构建键值对,纪录每一节点的父节点,这样当我们搜索到符合要求的叶节点时,我们可沿叶节点的父节点一路向上回溯,直到根节点.关于该方法的实现后文会给出java代码.后来我看了其他人的题解,发现在此处使用键值对有点繁琐,增加了额外的空间复杂度与时间复杂度.考虑当前函数的递归调用自然而然的维护了从根节点到当前节点的一条路径.因此我们可在自上而下遍历节点的过程中,记录当前路径中的节点值,如果到达符合要求的叶节点处,我们将该条路径上的值复制,然后添加到总路径中即可.我们也给出这种算法的java代码.
java算法
方法一:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//使用键值对纪录当前节点的父节点
Map<TreeNode, TreeNode> map = new HashMap<>();
Stack<TreeNode> stack = new Stack<>();
private void _pathSum(TreeNode x, int sum, int currentVal, List<List<Integer>> paths){
if(x == null)
return;
if(x.val + currentVal == sum && x.left == null && x.right == null){
//如果当前找到一条路径,则回溯这条路径
TreeNode cur = x;
while(cur != null){
stack.push(cur);
cur = map.get(cur);
}
List<Integer> path = new LinkedList<>();
while(!stack.isEmpty())
path.add(stack.pop().val);
paths.add(path);
}
if(x.left != null){
map.put(x.left, x);
_pathSum(x.left, sum, currentVal+x.val, paths);
}
if(x.right != null){
map.put(x.right, x);
_pathSum(x.right, sum, currentVal+x.val, paths);
}
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
map.put(root, null);
List<List<Integer>> paths = new LinkedList<>();
_pathSum(root, sum, 0, paths);
return paths;
}
}
方法二:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//使用一个列表来保存当前函数递归调用栈上的节点值
private void _pathSum(TreeNode x, int sum, List<Integer> currentPath, List<List<Integer>> paths){
if(x == null)
return;
currentPath.add(x.val);
sum -= x.val;
if(sum == 0 && x.left == null && x.right == null){//如果当前找到一条路径
List<Integer> path = new ArrayList(currentPath);
paths.add(path);
}
_pathSum(x.left, sum, currentPath, paths);
_pathSum(x.right, sum, currentPath, paths);
currentPath.remove(currentPath.size()-1); //移除最后一个元素,退栈;
sum += x.val;
return;
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> paths = new LinkedList<>();
List<Integer> currentPath = new LinkedList<>();
_pathSum(root, sum, currentPath, paths);
return paths;
}
}