𝑰’𝒎 𝒉𝒉𝒈, 𝑰 𝒂𝒎 𝒂 𝒈𝒓𝒂𝒅𝒖𝒂𝒕𝒆 𝒔𝒕𝒖𝒅𝒆𝒏𝒕 𝒇𝒓𝒐𝒎 𝑵𝒂𝒏𝒋𝒊𝒏𝒈, 𝑪𝒉𝒊𝒏𝒂.
- 🏫 𝑺𝒉𝒄𝒐𝒐𝒍: 𝑯𝒐𝒉𝒂𝒊 𝑼𝒏𝒊𝒗𝒆𝒓𝒔𝒊𝒕𝒚
- 🌱 𝑳𝒆𝒂𝒓𝒏𝒊𝒏𝒈: 𝑰’𝒎 𝒄𝒖𝒓𝒓𝒆𝒏𝒕𝒍𝒚 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈 𝒅𝒆𝒔𝒊𝒈𝒏 𝒑𝒂𝒕𝒕𝒆𝒓𝒏, 𝑳𝒆𝒆𝒕𝒄𝒐𝒅𝒆, 𝒅𝒊𝒔𝒕𝒓𝒊𝒃𝒖𝒕𝒆𝒅 𝒔𝒚𝒔𝒕𝒆𝒎, 𝒎𝒊𝒅𝒅𝒍𝒆𝒘𝒂𝒓𝒆 𝒂𝒏𝒅 𝒔𝒐 𝒐𝒏.
- 💓 𝑯𝒐𝒘 𝒕𝒐 𝒓𝒆𝒂𝒄𝒉 𝒎𝒆:𝑽𝑿
- 📚 𝑴𝒚 𝒃𝒍𝒐𝒈: 𝒉𝒕𝒕𝒑𝒔://𝒉𝒉𝒈𝒚𝒚𝒅𝒔.𝒃𝒍𝒐𝒈.𝒄𝒔𝒅𝒏.𝒏𝒆𝒕/
- 💼 𝑷𝒓𝒐𝒇𝒆𝒔𝒔𝒊𝒐𝒏𝒂𝒍 𝒔𝒌𝒊𝒍𝒍𝒔:𝒎𝒚 𝒅𝒓𝒆𝒂𝒎
1-1: Overview
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
示例 1:
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。
示例 2:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3
提示:
二叉树的节点个数的范围是 [0,1000]
-109 <= Node.val <= 109
-1000 <= targetSum <= 1000
通过次数159,510提交次数279,189
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-sum-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1-2: Solution
你看的懂官网或者那个精选的代码吗?我是看不懂的。。或者说有些地方,他们觉得简单没写吧。所以,我再自己写一个,只为了之后多刷打基础。
variables:,少就少在没有给一些变量作解释。对新手不友好啊
- prefix sum: the sum of nodes from the root to the current.
- map: key: the current prefix sum of the path; value: the number of the nodes whoes prefix sum equal to the key.
- cur: the prefix sum of the current node (including the current node)
- res: count the result which meets the requirements of the question.
- prefix sum: 前缀和,总根节点到当前节点的值的和
- map: key: 某个节点的前缀和; value: 前缀和=key的一共有多少个.
- cur: 当前节点的前缀和
- res: 计数符合要求的答案(个数)
正常来说,判断是否有前缀和等于某一条路径的时候应该用true和false啊,那这里map的value为什么不是Boolean呢?你看,这里节点的值有正有负,所以和等于某一条路径的,可能不止一条。
Example:
count the targetSum == 5 找到路径等于5的例子
Why use a vitrtual node? Think the linked list which has one external head. In this situation, the function is the same. At the same time, I recall that dp use external space to simplify the initail process.
为什么用虚拟节点?就像是单链表中额外的头结点,同时我又想到了dp中,通过那额外的一行一列,使得初始化过程简单,甚至避免了初始化。这里仅仅是为了,大家都有一个标杆,root节点也有了依靠。
public class Solution {
Map<Long, Integer> map = new HashMap<>();
int res = 0;
public int pathSum(TreeNode root, int targetSum) {
// 这里就是那个虚拟节点
map.put(0L, 1);
dfs(root, 0, targetSum);
return res;
}
public void dfs(TreeNode root, long cur, int targetSum) {
if (root == null) {
return;
}
cur += root.val;
res += map.getOrDefault(cur - targetSum, 0);
map.put(cur, map.getOrDefault(cur, 0) + 1);
dfs(root.left, cur, targetSum);
dfs(root.right, cur, targetSum);
// 回溯,至于为什么这么写,你需要基本的回溯常识,这里因为我很明白,所以就不写了,
// 注意cur为什么不用回溯?因为cur是局部变量,而map是递归过程中公用的
map.put(cur, map.getOrDefault(cur, 0) - 1);
}
}