这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战
题目
面试题 04.12. 求和路径
给定一棵二叉树,其中每个节点都含有一个整数数值(该值或正或负)。设计一个算法,打印节点数值总和等于某个给定值的所有路径的数量。注意,路径不一定非得从二叉树的根节点或叶节点开始或结束,但是其方向必须向下(只能从父节点指向子节点方向)。
示例:
给定如下二叉树,以及目标和 sum = 22
,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
复制代码
返回:
3
解释: 和为 22 的路径有:[5,4,11,2], [5,8,4,5], [4,11,7]
复制代码
提示:
节点总数 <= 10000
思路
- 从上往下,枚举每个节点作为根节点的情况,这样子一轮BFS遍历我们就可以枚举出所有的可能性;
- 每个节点作为根节点的时候,它有可能走左子节点这条路,也有可能走右子节点这条路,而且每一步都会面临这样子的选择,那么我们可以把这个问题转换为递归问题;
- 求和
sum
, 走过了当前节点之后我们就得减去当前节点的值,那么下一轮只要找到sum - 当前节点的值
相等的值即可; - 找到了后我们还要不要往下找呢,很多小伙伴可能会陷入一个思维误区,觉得我已经找到了还要往下干嘛?实际上这道题目并没有告诉我们节点的值是正整数,意味着值有可能是
0
或者负数,那么如果下一个节点是0
,加上当前节点还是原本的值,但它又算是另外一条路径。所以这道题目我们找到了不算完事,必须完完整整的从每个节点往下扫描一次; - 每次当前节点的值和我们要找的
sum
相同时,我们匹配到的结果+1,然后继续走左右节点直至尽头,最终返回每个节点的所有匹配上的数量总和即可。
实现
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} sum
* @return {number}
*/
var pathSum = function(root, sum) {
if (!root) return 0;
let reuslt = 0;
let queue = [ root ];
// 广度优先搜索,枚举每个节点作为起始节点的可能
while (queue.length) {
queue = queue.reduce((total, cur) => {
// 当前节点作为根节点能有多少条路径匹配,加上
reuslt += findNode(cur, sum);
// 统计下一轮的有效值
cur.left && total.push(cur.left);
cur.right && total.push(cur.right);
return total;
}, []);
}
return reuslt;
};
// 找找当前节点下有多少个符合条件的路径
function findNode(node, sum) {
if (!node) return 0;
let count = 0;
// 如果当前值就是要求的和,那么结果+1
if (node.val === sum) {
count++;
}
// 找到不算完,下一个值可能是0,那么依然算多一条
// 下次找的值只需要是当前求的和 - 当前值的差值
count += findNode(node.left, sum - node.val);
count += findNode(node.right, sum - node.val);
return count;
}
复制代码
结果
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。