题目概览
给定一个二叉树的根节点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] -10^9 <= Node.val <= 10^9-1000 <= targetSum <= 1000
来源:437. 路径总和 III - 力扣(LeetCode)
解题分析
方法一:深度遍历
如果只是求经过当前根节点的路径之和为 targetSum,那么只需要从当前根节点出发,不断遍历左右节点,遍历依次 targetSum - 当前节点的值,若 targetSum = 当前节点的值,就记录一个路径,直到所有遍历完成,这样就得到这个根节点的所有满足条件路径个数。
由于题目要求可以不经过根节点,因此我们只需要遍历所有的节点,将每个节点作为根节点,用上面的方法求出路径个数,再加起来即可。
时间复杂度:O(n²)
空间复杂度:O(n)
/** * Definition for a binary tree node. * public 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 { public int pathSum(TreeNode root, int targetSum) { if (root == null) { return 0; } int sum = pathSum(root.left, targetSum) + pathSum(root.right, targetSum) + sum(root, targetSum); return sum; } public int sum(TreeNode root, long targetSum) { if (root == null) { return 0; } int curSum = root.val == targetSum ? 1 : 0; int leftSum = sum(root.left, targetSum - root.val); int rightSum = sum(root.right, targetSum - root.val); return leftSum + rightSum + curSum; } }方法二:前缀和
以上图(示例一)为例, 5 + 3 的路径可以看做 10 + 5 + 3 的路径 减去 10 的前缀路径。因此我们可以用中序遍历(根 - 左 - 右)的方式,记录每次遍历的前缀和(用map变量 prefix 表示,key 为前缀和,value 为出现个数)和到当前的总路径(cur),那么:
- 满足路径和为 targetSum 的路径个数就为:当前总路径 - targetSum 的前缀和个数,即 prefix.get( cur - targetSum )。
- 当前总路径 等于 targetSum 时,也算满足条件,因此还要再前缀和中存储 0-1 的映射。
- 当前节点遍历完成时,由于当前节点的前缀和 在上层的节点用不到,需要及时清除。
时间复杂度:O(n)
空间复杂度:O(n)
/** * Definition for a binary tree node. * public 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 { public int pathSum(TreeNode root, int targetSum) { Map<Long, Integer> prefix = new HashMap<>(); prefix.put(0L, 1); return pathSum(root, targetSum, prefix, 0L); } public int pathSum(TreeNode root, int targetSum, Map<Long, Integer> prefix, long cur) { if (root == null) { return 0; } cur += root.val; int sum = prefix.getOrDefault(cur - targetSum, 0); prefix.put(cur, prefix.getOrDefault(cur, 0) + 1); sum += pathSum(root.left, targetSum, prefix, cur); sum += pathSum(root.right, targetSum, prefix, cur); prefix.put(cur, prefix.getOrDefault(cur, 0) - 1); return sum; } }