二叉树(十六)--二叉树中和为某一值的路径
来源:LeetCode
难度:中等
描述:
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
示例1:
给定如下二叉树,以及目标和 target = 22
        返回:
分析:
本题的要求是,让我们找到所有满足从「根节点」到某个「叶子节点」经过的路径上的节点之和等于目标和的路径。
因此我们需要对树进行遍历,并且在遍历时记录从根节点到当前节点的路径。此处介绍两种解法,具体步骤如下:
解题
方法一:深度优先遍历法
思路:
采用深度优先遍历的方式,枚举每一条从根节点到叶子节点的路径。当我们遍历到叶子节点,且此时target和当前节点值一致时,我们就找到了一条满足条件的路径。
注意,我们遍历完左右子树后,需要将记录的本节点从路径中删除
代码:
 1public List<List<Integer>> pathSum(TreeNode root, int target) {
 2    if (root == null) {
 3        return new ArrayList<>();
 4    }
 5    List<List<Integer>> ansList = new ArrayList<>();
 6    //路径数组
 7    List<Integer> pathList = new ArrayList<>();
 8    findTargetPath(root, target, ansList, pathList);
 9    return ansList;
10}
11private void findTargetPath(TreeNode root, int target, 
12                            List<List<Integer>> ansList, List<Integer> pathList) {
13    if (root == null) {
14        return;
15    }
16    //本节点存入数组
17    pathList.add(root.val);
18    //target减去本节点
19    target -= root.val;
20    if (target == 0 && root.left == null && root.right == null) {
21        //target减去本节点为0 且本节点刚好为叶子节点,找到一条路径
22        ansList.add(new ArrayList<>(pathList));
23    }
24    //递归左右子树
25    findTargetPath(root.left, target, ansList, pathList);
26    findTargetPath(root.right, target, ansList, pathList);
27    //回溯、删除本节点
28    pathList.remove(pathList.size() - 1);
29}
时间复杂度:O(n * n) n为节点个数
空间复杂度:O(n)
方法二:父节点记录法
思路:
        首先,咱们遍历一次二叉树,采用hash表记录每个节点和父节点的映射关系。同时,将父节点的值与本节点的值求和作为本节点的新值
        之后,遍历hash中的每个节点,如果该节点的值和target一致,且其左右节点为空,表明该节点为符合要求的叶子节点。根据hash表,找到该节点到根节点的路径即可
代码:
 1private void buildNode2Father(TreeNode root, 
 2                              Map<TreeNode, TreeNode> node2Father) {
 3    if (root == null) {
 4        return;
 5    }
 6    //root节点就是父节点,将其左右子节点指向它即可
 7    if (root.left != null) {
 8        //将父节点的值与本节点的值求和作为本节点的新值
 9        root.left.val = root.left.val + root.val;
10        node2Father.put(root.left, root);
11        //处理左子树为父节点的情况
12        buildNode2Father(root.left, node2Father);
13    }
14    if (root.right != null) {
15        //将父节点的值与本节点的值求和作为本节点的新值
16        root.right.val = root.right.val + root.val;
17        node2Father.put(root.right, root);
18        //处理右子树为父节点的情况
19        buildNode2Father(root.right, node2Father);
20    }
21}
22
23
24public List<List<Integer>> pathSum(TreeNode root, int target) {
25    if (root == null) {
26        return new ArrayList<>();
27    }
28    List<List<Integer>> ansList = new ArrayList<>();
29    //路径数组
30    List<Integer> pathList = new ArrayList<>();
31    findTargetPath(root, target, ansList, pathList);
32    return ansList;
33}
34private void findTargetPath(TreeNode root, int target,
35                            List<List<Integer>> ansList, List<Integer> pathList) {
36    if (root == null) {
37        return;
38    }
39    //本节点存入数组
40    pathList.add(root.val);
41    //target减去本节点
42    target -= root.val;
43    if (target == 0 && root.left == null && root.right == null) {
44        //target减去本节点为0 且本节点刚好为叶子节点,找到一条路径
45        ansList.add(new ArrayList<>(pathList));
46    }
47    //递归左右子树
48    findTargetPath(root.left, target, ansList, pathList);
49    findTargetPath(root.right, target, ansList, pathList);
50    //回溯、删除本节点
51    pathList.remove(pathList.size() - 1);
52}
时间复杂度:O(n * n) n为节点个数
空间复杂度:O(n)
以上仅是个人思路解法,觉得还不错欢迎点赞关注分享
往期精彩推荐
 
        算法和数据结构  
        
         
         
        
      
 
       
     
         IT程序员日常算法、数据结构分享 
       
 
       
     Official Account 
   
 
  