package class07;
import java.util.ArrayList;
import java.util.List;
/**
* leetcode 113. 路径总和 II
* 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
* <p>
* 叶子节点 是指没有子节点的节点。
*/
//测试链接:https://leetcode.com/problems/path-sum-ii
public class Code04_PathSumII {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
/**
* @param root 根节点
* @param targetSum 目标和
* @return 包含所有路径的集合。也就是list嵌套list<Integer>
*/
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> ans = new ArrayList<>();
if (root == null) {
return ans;
}
ArrayList<Integer> path = new ArrayList<>();
process(root, path, 0, targetSum, ans);
return ans;
}
/**
* @param x 当前循环的节点
* @param path 路径
* @param preSum 之前路径累加和
* @param targetSum 目标和
* @param ans 包含所有路径的集合
*/
public static void process(TreeNode x, List<Integer> path, int preSum, int targetSum, List<List<Integer>> ans) {
if (x.left == null && x.right == null) {//如果当前节点是叶子节点
if (preSum + x.val == targetSum) {//如果之前累加和+当前节点的值 == 目标和
path.add(x.val);//将当前节点的值,添加到路径这个list集合中。
ans.add(copy(path));//最后的结果,也添加上当前path。也就是ans集合又多了一个元素。
//清理现场。因为下一步要return了,即这条路径走完后,要退一步,走另一条路径了。
//所有要删除最后一个元素。否则最后的结果就会多出一个或者多个元素。结果就不对了。
path.remove(path.size() - 1);
}
return;
}
//如果x不是叶子节点
path.add(x.val);//将当前节点添加到路径中
preSum += x.val;//将当前节点的值添加到,之前累加和中。
if (x.left != null) {//如果当前节点的左子树不是空
process(x.left, path, preSum, targetSum, ans);//递归去
}
if (x.right != null) {//如果当前节点的右子树不是空
process(x.right, path, preSum, targetSum, ans);//递归去
}
path.remove(path.size() - 1);//attention:清理现场
}
/**
* 复制list
* <p>
* 因为最后的结果ans,要add一个或者多个path。而原来的path要继续它后面的操作。ans的add path的操作,不能影响原来的path。
* 所有就复制出一份path,供ans做add操作。之前的path该做什么操作,就继续什么操作。
*
* @param path 路径集合
* @return 一个新的list集合。也就是一个复制品。
*/
public static List<Integer> copy(List<Integer> path) {
List<Integer> ans = new ArrayList<>();
for (Integer num : path) {
ans.add(num);
}
return ans;
}
}