LeetCode—437.路径总和 III[Path Sum III]——分析及代码[Java]
一、题目
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过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)
链接:https://leetcode-cn.com/problems/path-sum-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. DFS 递归
(1)思路
因为路径可以任何节点为起始节点,并且方向限定向下,考虑可以 DFS 方式进行遍历的同时,计算各路径总和。
为便于递归,可传递路径总和与 sum 的差值,通过其是否为 0 直接进行判断。
(2)代码
class Solution {
int ans = 0;
public int pathSum(TreeNode root, int sum) {
if (root == null)
return ans;
DFS(root, sum);
if (root.left != null)
pathSum(root.left, sum);
if (root.right != null)
pathSum(root.right, sum);
return ans;
}
public int DFS(TreeNode node, int pSum) {
pSum -= node.val;
if (pSum == 0)
ans++;
if (node.left != null)
DFS(node.left, pSum);
if (node.right != null)
DFS(node.right, pSum);
return pSum;
}
}
(3)结果
执行用时 :22 ms, 在所有 Java 提交中击败了 76.86% 的用户;
内存消耗 :39.3 MB, 在所有 Java 提交中击败了 91.64% 的用户。
2. 前缀和
(1)思路
在前述方法的基础上,设计一个哈希表 prefix,记录当前路径上的前缀和数值及出现次数。结合深度优先遍历,可将时间复杂度降低到 O(n)。
(2)代码
class Solution {
Map<Integer, Integer> prefix = new HashMap<>();//记录当前路径上的前缀和数值及出现次数
int targetSum;
public int pathSum(TreeNode root, int targetSum) {
prefix.put(0, 1);//添加初始值,空路径前缀和为0
this.targetSum = targetSum;
return dfs(root, 0);//结合深度优先遍历方法求解
}
public int dfs(TreeNode root, int curr) {
if (root == null)//空节点,路径数量为0
return 0;
int cnt = 0;//当前节点及其子树中符合要求的路径数量
curr += root.val;//更新当前路径的前缀和
cnt += prefix.getOrDefault(curr - targetSum, 0);//添加以当前节点为末位子节点的路径数量
prefix.put(curr, prefix.getOrDefault(curr, 0) + 1);//将当前前缀和加入哈希表
cnt += dfs(root.left, curr);//统计左子树中的路径数量
cnt += dfs(root.right, curr);//统计右子树中的路径数量
prefix.put(curr, prefix.get(curr) - 1);//将当前前缀和移出哈希表
return cnt;
}
}
(3)结果
执行用时 :2 ms,在所有 Java 提交中击败了 100.00% 的用户;
内存消耗 :37.9 MB,在所有 Java 提交中击败了 92.42% 的用户。
三、其他
暂无。