开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
引言
算法的技能对于程序员是百益而无一害,作为程序员无论是前端还是后端算法技能对于我们都是十分十分的重要,我将陆续整理并讲解前端程序员必须掌握的经典算法。
题目描述
给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。
每条从根节点到叶节点的路径都代表一个数字:
- 例如,从根节点到叶节点的路径
1 -> 2 -> 3表示数字123。
计算从根节点到叶节点生成的 所有数字之和 。
叶节点 是指没有子节点的节点。
示例 1:
输入: root = [1,2,3]
输出: 25
解释:
从根到叶子节点路径 1->2 代表数字 12
从根到叶子节点路径 1->3 代表数字 13
因此,数字总和 = 12 + 13 = 25
示例 2:
输入: root = [4,9,0,5,1]
输出: 1026
解释:
从根到叶子节点路径 4->9->5 代表数字 495
从根到叶子节点路径 4->9->1 代表数字 491
从根到叶子节点路径 4->0 代表数字 40
因此,数字总和 = 495 + 491 + 40 = 1026
提示:
- 树中节点的数目在范围
[1, 1000]内 0 <= Node.val <= 9- 树的深度不超过
10
分析
根据题目的分析,我们如何设计求根到叶子节点的和?按照二叉树的特点我们使用队列的层序遍历结合并查集树存储父亲信息共同完成
- 使用队列保存所有同一层的节点信息
- 使用map结构保存所有节点的父亲信息,根节点的父亲初始为空
- 层序遍历队列,然后标记每个节点的父亲。
- 遍历结束后,找到所有的叶子节点,每个节点都按照并查集结构一层层的向上累加父亲的数据,
- 返回累加的数据。
解答
var sumNumbers = function(root) {
let sum = 0
let que = []
let rears = []
let m = new Map()
if(!root) return 0
que.push(root)
m.set(root,null)
while(que.length) {
let len = que.length
for(let i=0;i<len;i++) {
let node = que.shift()
if(node.left) {
que.push(node.left)
m.set(node.left,node)
}
if(node.right) {
que.push(node.right)
m.set(node.right,node)
}
if(!node.left && !node.right) rears.push(node)
}
}
//开始统计
for(let i=0;i<rears.length;i++) {
let node = rears[i]
let total = 0
let count = 0
while(node) {
total = total + node.val * Math.pow(10,count)
count++
node = m.get(node)
}
sum += total
}
return sum
};
通过题目的分析,我们使用了队列加map的两种数据结构完成了所有根到叶子的节点和,其中map模拟的是并查集树的结构。
总结
通过对根到叶子节点和的求解,我们学到了如何使用队列在层序遍历的同时结合map结果巧妙的解决二叉树的根到叶子和的问题。