Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目:给定二叉树的根节点root,以及一个整数targetSum,求此二叉树中节点值之和等于targetSum的路径的数目。此路径不需要从根节点开始也不需要在叶子节点结束。
解题思路
本题和LeetCode 560那题很类似,可以先理解LeetCode 560这题再来看本题。
和560那题一样,本题也可使用暴力解法,解题步骤为:
首先确定根节点,由此根节点向下遍历,每次遍历都累加路径之和,当路径之和等于targetSum时即该路径满足条件,直到遍历到叶子节点。
以上面的思路将二叉树中每个节点都这样遍历一遍,可得代码如下:
public int pathSum(TreeNode root, int targetSum) {
if(root == null) return 0;
int res = rootSum(root, targetSum);
res += pathSum(root.left, targetSum);
res += pathSum(root.right, targetSum);
return res;
}
public int rootSum(TreeNode root, int targetSum){
if(root == null) return 0;
int res = 0;
if(targetSum == root.val) res++;
res += rootSum(root.left, targetSum-root.val);
res += rootSum(root.right, targetSum-root.val);
return res;
}
上述算法的时间复杂度为, 空间复杂度为。
前缀和 + 哈希
实际上,在我们遍历一整颗树的时候,我们已经将重要信息保存下来了,这个重要信息就是前缀和,我们想象一下,对于一颗只有左子树的二叉树,如1-> 2-> 3,假设此时的target为3,我们保留的前缀和树为1 -> 3 -> 6,当我们遍历到6的时候,此时树中存在前缀和为6-3=3的路径,则此时前缀和为3到前缀和为6的这条路径必定存在一条满足的路径。
表达的不清楚,这篇题解写的很好,可以参考: 对前缀和解法的一点解释 - 路径总和 III 代码如下:
public int pathSum2(TreeNode root, int targetSum) {
if(root == null) return 0;
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
return rootSum2(root, targetSum, 0, map);
}
public int rootSum2(TreeNode root, int targetSum, int currSum, HashMap<Integer, Integer> map){
if(root == null) return 0;
int res = 0;
currSum += root.val;
if(map.containsKey(currSum-targetSum)) res += map.get(currSum-targetSum);
map.put(currSum, map.getOrDefault(currSum, 0) + 1);
res += rootSum2(root.left, targetSum, currSum, map);
res += rootSum2(root.right, targetSum, currSum, map);
map.put(currSum, map.get(currSum) - 1);
return res;
}
时间复杂度和空间复杂度都是。