小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
关于树的结构与遍历可以看我之前的博文:二叉树的结构与遍历,这里说了结构,与遍历方式,有递归和非递归的遍历方式,前序,中序,后序遍历方式的多种实现,是做树类的算法题的基础~ 还有刚刚发布的层序遍历博文二叉树的层序遍历 - 广度优先遍历BFS
112. 路径总和
给你二叉树的根节点
root和一个表示目标和的整数targetSum,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和targetSum。
【解法一】递归
使用递归来做这题就变成简单题了~
思路就是: 从根节点开始遍历整颗树,将目标和整数减去当前节点的值(targetSum - root.val),然后递归调用... 直到遇到叶子节点,此时判断是否符合条件,符合条件就返回true,否则就返回false。
具体的代码编写和思路直接看我代码上的注释吧,写的很详细~
var hasPathSum = function(root, targetSum) {
// 节点不存在 返回false
if(!root) return false
// 左右子树都不存在,说明是叶子节点,判断是否符合条件
if(!root.left && !root.right) return targetSum === root.val
// 到这里就是:节点存在,左右子树存在一个或者都存在,也就是内部节点
// 遍历左右子树,更新总和为 总和删除当前节点的值
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val)
};
【解法二】BFS - 双队列
如果不能使用递归,那我们就要使用队列来模拟了,这里我们使用两个队列,一个用来存储节点,一个用来存储节点的总和
var hasPathSum = function(root, targetSum) {
if(!root) return false
// 创建两个队列
// 用来存储节点
let nodeQue = []
// 用来存储根节点到这个节点的总和
let valQue = []
// 先将根节点入队列
nodeQue.unshift(root)
valQue.unshift(root.val)
while(nodeQue.length > 0){
// 将队头元素取出来得到节点root和值temp
let root = nodeQue.pop()
let temp = valQue.pop()
// 如果这个节点是叶子节点(没有左右孩子)
if(!root.left && !root.right){
// 如何符合要求返回true 并 退出函数
if(temp === targetSum) return true
// 不满足要求 下面的都不会满足,就进行下一轮循环了
}
// 有左孩子就进来
if(root.left){
// 左孩子进队列
nodeQue.unshift(root.left)
// 保存此时路径总和
valQue.unshift(root.left.val + temp)
}
// 有右孩子就进来
if(root.right){
// 右孩子进队列
nodeQue.unshift(root.right)
// 保存此时路径总和
valQue.unshift(root.right.val + temp)
}
}
// 循环走完都没有返回true就说明没有符合要求的路径总和
return false
};
129. 求根节点到叶节点数字之和
给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字: 例如,从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。 计算从根节点到叶节点生成的 所有数字之和 。
这题和112题的解法一模一样
【解法一】BFS - 双队列
var sumNumbers = function(root) {
let nodeQue = []
let valQue = []
let result = 0
nodeQue.unshift(root)
valQue.unshift(root.val)
while(nodeQue.length > 0){
let root = nodeQue.pop()
let temp = valQue.pop()
if(!root.left && !root.right) {
result += temp
}
if(root.left){
nodeQue.unshift(root.left)
valQue.unshift(root.left.val + temp * 10)
}
if(root.right){
nodeQue.unshift(root.right)
valQue.unshift(root.right.val + temp * 10)
}
}
return result
};
【解法二】递归
var sumNumbers = function(root) {
return dfs(root, 0)
};
function dfs(root, prevSum){
// 节点不存在直接返回0
if(!root) return 0
// 根节点到当前节点数字之和
let sum = prevSum * 10 + root.val
// 如果是叶子节点,就返回sum
if(!root.left && !root.right) return sum
// 不是叶子节点,就递归,并把当前的和传给孩子节点
return dfs(root.left, sum) + dfs(root.right, sum)
}