路径总和 III
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
示例1:
输入: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出: 3
解释: 和等于 8 的路径有 3 条,如图所示。
解题思路
可以使用深度优先搜索(DFS)进行解决。
- 1、对于每个节点,可以该节点作为起点,向下递归搜索路径,并计算路径和是否等于目标和 targetSum。
- 2、对于每个节点,计算从该节点开始的路径中和为目标和targetSum的路径数量。
- 3、对于每个节点,分别计算从左子树和右子树开始的路径中和为目标和targetSum的路径数量。
- 4、最终结果为当前节点路径数量加上左子树路径数量和右子树路径数量的总和。
Java实现(int类型大数会有计算溢出问题过不了leetcode官方测试)
public class PathSumIII {
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public int pathSum(TreeNode root, int targetSum) {
if (root == null) {
return 0;
}
// 从当前节点开始的路径数目 + 从左子树开始的路径数目 + 从右子树开始的路径数目
return countPath(root, targetSum) + pathSum(root.left, targetSum) + pathSum(root.right, targetSum);
}
//计算该节点符合路径数
private int countPath(TreeNode node, int targetSum) {
if (node == null) {
return 0;
}
int count = 0;
if (node.val == targetSum) {
count++;
}
count += countPath(node.left, targetSum - node.val);
count += countPath(node.right, targetSum - node.val);
return count;
}
// 示例测试
public static void main(String[] args) {
PathSumIII solution = new PathSumIII();
// 10
// / \
// 5 -3
// / \ \
// 3 2 11
// / \
// 3 -2
// /
// 1
// 构造二叉树
TreeNode root = new TreeNode(10);
root.left = new TreeNode(5);
root.right = new TreeNode(-3);
root.left.left = new TreeNode(3);
root.left.right = new TreeNode(2);
root.right.right = new TreeNode(11);
root.left.left.left = new TreeNode(3);
root.left.left.right = new TreeNode(-2);
root.left.right.right = new TreeNode(1);
int targetSum = 8;
System.out.println(solution.pathSum(root, targetSum)); // 输出 3
}
}
Java实现2(节点计算时转为long类型计算)
public class PathSumIII {
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public int pathSum(TreeNode root, int targetSum) {
if (root == null) {
return 0;
}
// 从当前节点开始的路径数目 + 从左子树开始的路径数目 + 从右子树开始的路径数目
return countPath(root, (long) targetSum) + pathSum(root.left, targetSum) + pathSum(root.right, targetSum);
}
//计算该节点符合路径数
private int countPath(TreeNode node, long targetSum) {
if (node == null) {
return 0;
}
int count = 0;
if (node.val == targetSum) {
count++;
}
//leetcode 官方测试案例会溢出不过,targetSum和node.val 改为long进行计算
long longNodeValue = node.val;
count += countPath(node.left, targetSum - longNodeValue);
count += countPath(node.right, targetSum - node.val);
return count;
}
// 示例测试
public static void main(String[] args) {
PathSumIII solution = new PathSumIII();
// 10
// / \
// 5 -3
// / \ \
// 3 2 11
// / \
// 3 -2
// /
// 1
// 构造二叉树
// TreeNode root = new TreeNode(10);
// root.left = new TreeNode(5);
// root.right = new TreeNode(-3);
// root.left.left = new TreeNode(3);
// root.left.right = new TreeNode(2);
// root.right.right = new TreeNode(11);
// root.left.left.left = new TreeNode(3);
// root.left.left.right = new TreeNode(-2);
// root.left.right.right = new TreeNode(1);
// int targetSum = 8;
// [1000000000,1000000000,null,294967296,null,1000000000,null,1000000000,null,1000000000]
TreeNode root = new TreeNode(1000000000);
root.left = new TreeNode(1000000000);
root.left.left = new TreeNode(294967296);
root.left.left.left = new TreeNode(1000000000);
root.left.left.left.left = new TreeNode(1000000000);
root.left.left.left.left.left = new TreeNode(1000000000);
int targetSum = 0;
System.out.println(solution.pathSum(root, targetSum)); // 输出 3
}
}
室间空间复杂度
- 时间复杂度:O(n^2),其中n是二叉树中的节点数,每个节点需要遍历一次,并且需要额外的时间计算从当前节点开始的路径数量。
- 空间复杂度:O(n),递归调用栈的深度为二叉树的高度。