48.路径总和 III
LCR 050. 路径总和 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
一、核心思路
这个问题要求统计二叉树中路径和等于目标值的路径总数(路径不需要从根节点开始,也不需要在叶子节点结束,但必须是自上而下的连续节点序列)。
核心解法是利用 前缀和 + 深度优先搜索(DFS) + 回溯,把 “找路径和” 的问题转化为 “找前缀和差值” 的问题,核心原理如下:
- 前缀和定义:从根节点到当前节点的路径上所有节点值的累加和,记为
currSum。 - 核心公式:如果存在某个节点的前缀和为
preSum,且currSum - preSum = targetSum,说明从该节点的下一个节点到当前节点的路径和正好是targetSum。 - 哈希表作用:用
preSumCount记录遍历过程中已经出现过的前缀和及其出现次数,避免重复计算,将时间复杂度从暴力法的 O(n2) 优化到 O(n)。
【具体思路见代码】来源:b0nalucas
import java.util.HashMap; import java.util.Map; // 首先确保TreeNode类的定义(如果环境中没有的话) class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } class Solution { private Map<Long, Integer> preSumCount = new HashMap<>(); private int target; public int pathSum(TreeNode root, int targetSum) { this.target = targetSum; preSumCount.put(0L, 1); // 初始化前缀和0出现1次 return dfs(root, 0L); } private int dfs(TreeNode root, Long currSum) { // 1. 递归终止条件:节点为空 if (root == null) return 0; int res = 0; // 2. 计算当前前缀和(包含当前节点值) currSum += root.val; // 3. 查找有多少个前缀和等于 currSum - target,这就是以当前节点为终点的符合条件的路径数 // 如果存在某个节点的前缀和为 preSum,且 currSum - preSum = targetSum, // 说明从该节点的下一个节点到当前节点的路径和正好是 targetSum。 // preSum = currSum - target res += preSumCount.getOrDefault(currSum - target, 0); // 4. 更新前缀和计数:当前前缀和出现次数+1 // 将当前计算出的前缀和 currSum 加入哈希表:如果已存在则次数 + 1,不存在则初始化为 1。 preSumCount.put(currSum, preSumCount.getOrDefault(currSum, 0) + 1); // 5. 递归遍历左右子树 res += dfs(root.left, currSum); res += dfs(root.right, currSum); // 6. 回溯:恢复当前前缀和的计数(移除当前节点的影响) // 恢复本层记录过的前缀和,恢复状态的原因是因为防止在不同分支上的节点满足target preSumCount.put(currSum, preSumCount.get(currSum) - 1); return res; } }

浙公网安备 33010602011771号