题目

给定一个二叉树和一个目标和,找出所有从根节点到叶子节点的路径,这些路径上的节点值之和等于目标和。

引言

路径总和II问题是一个与路径和相关的常见问题。与路径和问题不同,路径总和II需要找出所有满足条件的路径,而不仅仅是判断是否存在一条路径。

在这个问题中,我们要找出从根节点到叶子节点的所有路径,这些路径的节点值之和等于给定的目标和。我们可以使用回溯法来解决这个问题。

算法思路

  1. 定义一个递归函数 findPaths,该函数接受当前节点 node、目标和 target、当前路径 currentPath、结果集 result 作为参数。
  2. 在每个节点上,将当前节点的值添加到 currentPath 中。
  3. 如果当前节点是叶子节点且节点值等于目标和,将 currentPath 添加到 result 中。
  4. 递归调用 findPaths 函数来分别处理左子树和右子树。
  5. 回溯:在返回上一级之前,从 currentPath 中移除当前节点的值。
  6. 最终,返回 result,其中包含所有满足条件的路径。

代码实现

以下是使用 Java 实现的解决方案:

import java.util.ArrayList;
import java.util.List;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int val) {
        this.val = val;
    }
}

public class PathSumII {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> currentPath = new ArrayList<>();
        findPaths(root, targetSum, currentPath, result);
        return result;
    }

    private void findPaths(TreeNode node, int target, List<Integer> currentPath, List<List<Integer>> result) {
        if (node == null) {
            return;
        }

        currentPath.add(node.val);

        if (node.left == null && node.right == null && target == node.val) {
            // 当前节点是叶子节点且值等于目标和,将当前路径添加到结果中
            result.add(new ArrayList<>(currentPath));
        } else {
            // 递归查找左子树和右子树
            findPaths(node.left, target - node.val, currentPath, result);
            findPaths(node.right, target - node.val, currentPath, result);
        }

        // 回溯:移除当前节点,返回上一级
        currentPath.remove(currentPath.size() - 1);
    }

    public static void main(String[] args) {
        PathSumII solution = new PathSumII();

        // 创建一个示例二叉树
        TreeNode root = new TreeNode(5);
        root.left = new TreeNode(4);
        root.right = new TreeNode(8);
        root.left.left = new TreeNode(11);
        root.right.left = new TreeNode(13);
        root.right.right = new TreeNode(4);
        root.left.left.left = new TreeNode(7);
        root.left.left.right = new TreeNode(2);
        root.right.right.right = new TreeNode(1);

        int targetSum = 22;
        List<List<Integer>> paths = solution.pathSum(root, targetSum);

        // 打印结果
        for (List<Integer> path : paths) {
            System.out.println("路径: " + path);
        }
    }
}

算法分析

  • 时间复杂度:对于每个节点,我们只需遍历一次,因此时间复杂度是O(n),其中n是二叉树的节点数。
  • 空间复杂度:递归调用栈的深度最多为树的高度,所以空间复杂度是O(h),其中h是二叉树的高度。

示例和测试

假设给定一个示例二叉树 root 和目标和 targetSum,如下所示:

         5
        / \
       4   8
      /   / \
     11  13  4
    /  \      \
   7    2      1

根据算法,我们可以找到所有满足条件的路径。我们可以使用以下代码进行测试:

public class Main {
    public static void main(String[] args) {
        PathSumII solution = new PathSumII();

        TreeNode root = new TreeNode(5);
        root.left = new TreeNode(4);
        root.right = new TreeNode(8);
        root.left.left = new TreeNode(11);
        root.right.left = new TreeNode(13);
        root.right.right = new TreeNode(4);
        root.left.left.left = new TreeNode(7);
        root.left.left.right = new TreeNode(2);
        root.right.right.right = new TreeNode(1);

        int targetSum = 22;
        List<List<Integer>> paths = solution.pathSum(root, targetSum);

        // 打印结果
        for (List<Integer> path : paths) {
            System.out.println("路径: " + path);
        }
    }
}

总结

路径总和II问题要求找出所有满足条件的路径,这些路径的节点值之和等于给定的目标和。我们使用回溯法来解决这个问题,递归遍历树的每个节点,同时更新当前路径和目标和,当找到满足条件的路径时,将其添加到结果中。这个算法的时间复杂度是O(n),空间复杂度是O(h),其中n是二叉树的节点数,h是二叉树的高度。解决这个问题有助于理解回溯算法在树结构中的应用。

标签: 编程算法, 编程算法题, 编程算法大全, 编程算法流程, 算法设计与分析, 数据结构与算法, 算法优化, 算法实现, 常见编程算法, 编程算法入门, 编程算法进阶, 编程算法精通