Bootstrap

一起学习LeetCode热题100道(48/100)

48.路径总和 III(学习)

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

示例 1:
在这里插入图片描述
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

示例 2:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3

提示:
二叉树的节点个数的范围是 [0,1000]
-109 <= Node.val <= 109
-1000 <= targetSum <= 1000

解析:
一、pathSum函数:
1.这是主函数,接收根节点和目标和作为参数,并返回满足条件的路径数量。
2.初始化一个计数器count为0,用于记录满足条件的路径数量。
3.初始化一个Map对象prefixSums,用于存储从根节点到当前节点的路径和及其出现次数。初始时,将路径和为0的情况(表示空路径)的计4.数设为1。

二、DFS函数:
1.这是一个递归函数,用于深度优先搜索树。
2.参数node表示当前访问的节点,currentSum表示从根节点到当前节点的路径和(初始时为0)。
3.更新currentSum以包含当前节点的值。
4.检查是否存在之前的路径和,使得两者之差等于目标和。如果存在,则增加计数器count的值。
5.更新prefixSums中currentSum的计数(如果currentSum已经存在,则增加其计数;否则,将其添加到prefixSums中)。
6.递归地对左子树和右子树执行DFS。
7.注意:虽然代码中包含了回溯部分(即减少当前路径和的计数并从prefixSums中删除它),但在本问题中,由于树是无环的,并且我们不需要精确跟踪每条路径,因此这部分是多余的。在DFS结束后,prefixSums中的条目将自动表示所有可能的路径和及其出现次数。

三、从根节点开始DFS:
1.调用dfs(root, 0)从根节点开始搜索。

四、返回结果:
1.函数返回计数器count的值,即满足条件的路径数量。

var pathSum = function (root, targetSum) {
    let count = 0;
    const prefixSums = new Map(); // 存储从根到当前节点的路径和及其出现次数  
    prefixSums.set(0, 1); // 初始化,表示空路径和为0的情况有1种  

    // 深度优先搜索函数  
    function dfs(node, currentSum) {
        if (!node) return;

        // 更新当前路径和  
        currentSum += node.val;

        // 检查是否存在之前的路径和,使得两者之差等于目标值  
        if (prefixSums.has(currentSum - targetSum)) {
            count += prefixSums.get(currentSum - targetSum);
        }

        // 更新当前路径和的出现次数  
        prefixSums.set(currentSum, (prefixSums.get(currentSum) || 0) + 1);

        // 递归遍历左子树和右子树  
        dfs(node.left, currentSum);
        dfs(node.right, currentSum);

        // 回溯时,需要减去当前节点对路径和的贡献(可选,因为Map会自动处理重复键值)  
        // 但为了保持代码的清晰性和完整性,这里还是显式地处理一下  
        prefixSums.set(currentSum, prefixSums.get(currentSum) - 1);
        if (prefixSums.get(currentSum) === 0) {
            prefixSums.delete(currentSum);
        }
    }

    // 从根节点开始DFS  
    dfs(root, 0);

    return count;
};
;