leetcode 113. 路径总和 II

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;
    }

}

 

posted @ 2022-08-12 22:40  TheFloorIsNotTooHot  阅读(36)  评论(0)    收藏  举报