#LeetCode每日一题【二叉树专题】
- 路径总和 III
https://leetcode-cn.com/problems/path-sum-iii/ - 分析
解法1:二叉树中任意路径等于目标和,暴力解法,从二叉树的每一个节点向下寻找符合条件的路径,记录数目;再以同样的方式计算二叉树的所有其他的节点,即双重递归 - 实现
int ans = 0;
// 暴力搜索法:每个节点都去找有没有路径满足目标和
public int pathSum(TreeNode root, int targetSum) {
if (root == null) return ans;
nodePath(root, targetSum);
// 该层递归,遍历整棵树(即每一个节点都按照下面的思路去寻找路径和是否满足)
pathSum(root.left, targetSum);
pathSum(root.right, targetSum);
return ans;
}
// 从该结点出发,每个路径都去判断和是否相等
private void nodePath(TreeNode root, int targetSum) {
if (root == null) return;
if (root.val == targetSum) {
ans++;
}
nodePath(root.left, targetSum - root.val);
nodePath(root.right, targetSum - root.val);
}
LeetCode耗时:33ms
-
解法二
前缀和:看成类似于数组,在数组中寻找任意字串等于目标和,常用前缀和的方式:
前缀和:前n项之和,例如[1,2,3,4,5],各个位置的前缀和[1,3,6,10,15]
若节点j的前缀和=当前节点i前缀和-target,则节点j到节点i的路径和等于target
若节点j的前缀和=当前节点i前缀和,则节点j到节点i的路径和等于0常用解法:使用map保存前面出现的前缀和以及出现的次数,用于寻找目标和路径
树的话注意下回溯,即计算到根节点之后,在网上回溯的时候,将当前存储的路径和从map中去除 -
实现
// 求路径中子路径和等于目标和,可以使用前缀和
// 前缀和:前n项之和;若节点j的前缀和=当前节点i前缀和-target,则节点j到节点i的路径和等于target
// 通过map保存前缀和出现的次数
public int pathSum(TreeNode root, int targetSum) {
Map<Integer, Integer> prefix = new HashMap<>();
// 前缀和为0的有一个
prefix.put(0, 1);
return pathSum(root, prefix, targetSum, 0);
}
private int pathSum(TreeNode root, Map<Integer, Integer> prefix, int targetSum, int curr) {
if (root == null) return 0;
// 当前前缀和
curr += root.val;
int ans = prefix.getOrDefault(curr - targetSum, 0);
// 将当前前缀和放入map,之前若有该前缀和,则数量累计+1
prefix.put(curr, prefix.getOrDefault(curr, 0) + 1);
ans += pathSum(root.left, prefix, targetSum, curr);
ans += pathSum(root.right, prefix, targetSum, curr);
// 回溯,将当前前缀和从map中移除
prefix.put(curr, prefix.get(curr) - 1);
return ans;
}
LeetCode耗时:2ms
- 总结
- 数组等之类的寻找路径和的题目,首选前缀和解法