437. 路径总和 III
原题链接
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
示例:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ \ \
3 2 11
/ \ \
3 -2 1
返回 3。和等于 8 的路径有:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
要点
-
在 【LeetCode算法修炼+动画演示】—— 113. 路径总和 II 的基础上优化代码。
-
之前我们仅仅是在求到根结点的结果是否符合要求是吧。
那么从叶子节点为结尾的数组总共有多少个和能符合题目要求 。
假设你要求和5,并且获取到如下路径 arr: [1,-1,5] sum: ①5+(-1) = 5,② 5+(-1)+1 = 5
也就是说以当前节点结束时,共有两中情况符合。 -
那么题目告诉你不需要到叶子节点,也就是说每次遍历到一个节点都是有可能符合结果的。
解法
代码片段1
一种暴力的解法,只要求出以根结点开始所有符合结果。然后扩展到左右子树。
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
public int pathSumIII(TreeNode root, int sum) {
if (root == null) {//3.终止条件
return 0;
}
int[] arrs = new int[1];//记录符合情况的数组变量
pathSumIIIHelper(root, sum, arrs, new ArrayList<Integer>());//4.求出以当前节点符合情况的数量。
return arrs[0] + pathSumIII(root.left, sum) + pathSumIII(root.right, sum);//2.所以符合的情况等于 根结点+左右子树的结果数量和
}
public void pathSumIIIHelper(TreeNode root, int sum, int[] arrs) {
if (root == null) {
return;
}
if (root.val == sum) {
arrs[0]++;
}
pathSumIIIHelper(root.left, sum - root.val, arrs);
pathSumIIIHelper(root.right, sum - root.val, arrs);
}
代码片段2
时间复杂度: O ( n ) O(n) O(n)
//437. 路径总和 III 2
public int pathSumIII2(TreeNode root, int sum) {
if (root == null) {//0.终止条件。
return 0;
}
int[] arrs = new int[1];//1.记录结果
pathSumIII2Helper(root, sum, arrs, new int[1000], 0);//3.创建一个储存树节点元素的数组,求解结果。
return arrs[0];//2.返回结果
}
public void pathSumIII2Helper(TreeNode root, int sum, int[] arrs, int[] path, int h) {
if (root == null) {//4.终止条件
return;
}
path[h] = root.val;
int sumPath = 0;
for (int i = h; i >= 0; i--) {//7.以当前节点为结尾的数组总共有多少个和能符合题目要求。
sumPath += path[i];
if (sumPath == sum) {
arrs[0]++;
}
}
pathSumIII2Helper(root.left, sum, arrs, path, h + 1);//5.求左子树符合的数量
pathSumIII2Helper(root.right, sum, arrs, path, h + 1);//6.求右子树符合的数量
}