加载中...
437-路径总和 III(Path Sum III)
发表于:2021-12-03 | 分类: 中等
字数统计: 576 | 阅读时长: 2分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/path-sum-iii

英文原文

Given the root of a binary tree and an integer targetSum, return the number of paths where the sum of the values along the path equals targetSum.

The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes).

 

Example 1:

Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
Output: 3
Explanation: The paths that sum to 8 are shown.

Example 2:

Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
Output: 3

 

Constraints:

  • The number of nodes in the tree is in the range [0, 1000].
  • -109 <= Node.val <= 109
  • -1000 <= targetSum <= 1000

中文题目

给定一个二叉树的根节点 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 

通过代码

高赞题解

解题思路

这道题用到了一个概念,叫前缀和。就是到达当前元素的路径上,之前所有元素的和。

前缀和怎么应用呢?

在同一个路径之下(可以理解成二叉树从root节点出发,到叶子节点的某一条路径),如果两个数的前缀总和是相同的,那么这些节点之间的元素总和为零。进一步扩展相同的想法,如果前缀总和currSum,在节点A和节点B处相差target,则位于节点A和节点B之间的元素之和是target。

因为本题中的路径是一棵树,从根往任一节点的路径上(不走回头路),有且仅有一条路径,因为不存在环。(如果存在环,前缀和就不能用了,需要改造算法)

抵达当前节点(即B节点)后,将前缀和累加,然后查找在前缀和上,有没有前缀和currSum-target的节点(即A节点),存在即表示从A到B有一条路径之和满足条件的情况。结果加上满足前缀和currSum-target的节点的数量。然后递归进入左右子树。

左右子树遍历完成之后,回到当前层,需要把当前节点添加的前缀和去除。避免回溯之后影响上一层。因为思想是前缀和,不属于前缀的,我们就要去掉它。

核心代码


// 当前路径上的和

currSum += node.val;

// currSum-target相当于找路径的起点,起点的sum+target=currSum,当前点到起点的距离就是target

res += prefixSumCount.getOrDefault(currSum - target, 0);

// 更新路径上当前节点前缀和的个数

prefixSumCount.put(currSum, prefixSumCount.getOrDefault(currSum, 0) + 1);

代码


/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

class Solution {

    public int pathSum(TreeNode root, int sum) {

        // key是前缀和, value是大小为key的前缀和出现的次数

        Map<Integer, Integer> prefixSumCount = new HashMap<>();

        // 前缀和为0的一条路径

        prefixSumCount.put(0, 1);

        // 前缀和的递归回溯思路

        return recursionPathSum(root, prefixSumCount, sum, 0);

    }



    /**

     * 前缀和的递归回溯思路

     * 从当前节点反推到根节点(反推比较好理解,正向其实也只有一条),有且仅有一条路径,因为这是一棵树

     * 如果此前有和为currSum-target,而当前的和又为currSum,两者的差就肯定为target了

     * 所以前缀和对于当前路径来说是唯一的,当前记录的前缀和,在回溯结束,回到本层时去除,保证其不影响其他分支的结果

     * @param node 树节点

     * @param prefixSumCount 前缀和Map

     * @param target 目标值

     * @param currSum 当前路径和

     * @return 满足题意的解

     */

    private int recursionPathSum(TreeNode node, Map<Integer, Integer> prefixSumCount, int target, int currSum) {

        // 1.递归终止条件

        if (node == null) {

            return 0;

        }

        // 2.本层要做的事情

        int res = 0;

        // 当前路径上的和

        currSum += node.val;



        //---核心代码

        // 看看root到当前节点这条路上是否存在节点前缀和加target为currSum的路径

        // 当前节点->root节点反推,有且仅有一条路径,如果此前有和为currSum-target,而当前的和又为currSum,两者的差就肯定为target了

        // currSum-target相当于找路径的起点,起点的sum+target=currSum,当前点到起点的距离就是target

        res += prefixSumCount.getOrDefault(currSum - target, 0);

        // 更新路径上当前节点前缀和的个数

        prefixSumCount.put(currSum, prefixSumCount.getOrDefault(currSum, 0) + 1);

        //---核心代码



        // 3.进入下一层

        res += recursionPathSum(node.left, prefixSumCount, target, currSum);

        res += recursionPathSum(node.right, prefixSumCount, target, currSum);



        // 4.回到本层,恢复状态,去除当前节点的前缀和数量

        prefixSumCount.put(currSum, prefixSumCount.get(currSum) - 1);

        return res;

    }

}

时间复杂度:每个节点只遍历一次,O(N).

空间复杂度:开辟了一个hashMap,O(N).

统计信息

通过次数 提交次数 AC比率
131601 229277 57.4%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
路径总和 简单
路径总和 II 中等
路径总和 IV 中等
最长同值路径 中等
上一篇:
436-寻找右区间(Find Right Interval)
下一篇:
438-找到字符串中所有字母异位词(Find All Anagrams in a String)
本文目录
本文目录