解题思路:

1、采用深度优先搜索的方式,枚举每一条从根节点到叶子节点的路径。当我们遍历到叶子节点,且此时路径和恰为目标和时,我们就找到了一条满足条件的路径。
2、我们也可以采用广度优先搜索的方式,遍历这棵树。当我们遍历到叶子节点,且此时路径和恰为目标和时,我们就找到了一条满足条件的路径。为了节省空间,我们使用哈希表记录树中的每一个节点的父节点。每次找到一个满足条件的节点,我们就从该节点出发不断向父节点迭代,即可还原出从根节点到当前节点的路径。

举例说明:
采用深度优先搜索的方式:
二叉树:{10,5,12,4,7},   目标值:22
根据二叉树可以枚举出所有从根节点到叶子节点的路径【10,5,4】、【10,5,7】、【10,12】
将不同的路径节点值相加,并判断符合结果等于目标值的路径:【10,5,7】、【10,12】

图表题解:
步骤 二叉树序列 目标值 路径列表 返回路径集合
1 {10,5,12,4,7}
22 【10】
2 根左子树{5,4,7} 12 【10,5】
3 左子树{4} 7 【10,5,4】
4 右子树{7} 7 【10,5,7】
【10,5,7】
5 根右子树{12} 12 【10,12】
【10,5,7】,【10,12】

代码:

Python版本:
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回二维列表,内部每个列表表示找到的路径
    def FindPath(self, root, expectNumber):
        # write code here
        # 定义返回列表
        res = []
        
        def dfs(root, target, tmp):
            if not root:
                return
            # 判断搜索终止条件,达到叶节点停止
            if target == root.val and not root.left and not root.right:
                tmp += [root.val]
                res.append(tmp)
            # 递归左子树搜索
            if root.left:
                dfs(root.left, target-root.val, tmp + [root.val])
            # 递归右子树搜索
            if root.right:
                dfs(root.right, target-root.val, tmp + [root.val])
        # 深度优先搜索
        dfs(root, expectNumber, [])
        return res
JAVA版本:
import java.util.ArrayList;
import java.util.LinkedList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    //初始化集合
    ArrayList res = new ArrayList<>();
    LinkedListpath = new LinkedList<>(); 
    public ArrayList FindPath(TreeNode root,int target) {
        dfs(root, target);
        return res;
    }
    
    public void dfs(TreeNode root,int tar){
        
        if(root == null){
            return;
        }
        //将root节点放入路径集合
        path.add(root.val);
        //更新目标值,每放入一个节点,目标值应该相应减去对应节点的值,直到目标值为0
        tar -= root.val;
        //如果目标值减到了0 && 左节点为空 && 右节点为空 证明树已遍历完,此路径为目标路径
        if(tar==0 && root.left == null && root.right == null){
            res.add(new ArrayList(path));
        }
        // 递归左右子树
        dfs(root.left, tar);
        dfs(root.right, tar);
        //删除当前节点,在回溯过程中,此节点不在新路径上
        path.removeLast();
    }
}

复杂度分析:

时间复杂度:O(N^2),其中 N 是树的节点数。在最坏情况下,树的上半部分为链状,下半部分为完全二叉树,并且从根节点到每一个叶子节点的路径都符合题目要求。此时,路径的数目为 O(N),并且每一条路径的节点个数也为 O(N),因此要将这些路径全部添加进答案中,时间复杂度为 O(N^2)
空间复杂度:O(N),其中 N 是树的节点数。空间复杂度主要取决于返回列表空间的开销,元素个数不会超过树的节点数