「这是我参与11月更文挑战的第 21 天,活动详情查看:2021最后一次更文挑战」
刷算法题,从来不是为了记题,而是练习把实际的问题抽象成具体的数据结构或算法模型,然后利用对应的数据结构或算法模型来进行解题。个人觉得,带着这种思维刷题,不仅能解决面试问题,也能更多的学会在日常工作中思考,如何将实际的场景抽象成相应的算法模型,从而提高代码的质量和性能
求根节点到叶节点数字之和
题目来源:LeetCode-129. 求根节点到叶节点数字之和
题目描述
给你一个二叉树的根节点 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
解题
解法一:深度优先搜索
思路
其实这道题最容易想到的就是,如果能从左到右,或从右到左,得到每条路径上的数字就可以了,假设是从左到右,有没有发现就是前序遍历
前序遍历的思路,契合深度优先搜索的思想,就是一条路走到黑,没路了,就回退一步,找另一条路继续走下去,下边就是具体看怎么实现
首先可以发现的是,我们可以根据当前节点的值和子节点的值(左子节点或右子节点),来计算子节点表示的数字,即:子节点的数字 = 父节点的值*10 + 子节点的值
- 如果当前结点没有子节点,也就是它本身是叶子节点,那么就可以直接返回当前节点的数字
- 如果当前节点是非叶子节点,那它的数字,就是左右子节点数字的和
代码
// 深度优先搜索
func sumNumbers(root *TreeNode) int {
return dfs(root, 0)
}
func dfs(root *TreeNode, preNodeVal int) int {
if root == nil {
return 0
}
num := preNodeVal * 10 + root.Val
if root.Left == nil && root.Right == nil {
return num
}
return dfs(root.Left, num) + dfs(root.Right, num)
}
复制代码
解法二:广度优先搜索
思路
能用深度优先搜索解决的问题,基本都可以用广度优先搜索(反之亦然)
广度优先搜索的核心思想就是,先搜索所有离起点最近的节点,然后再搜索离七点次近的节点。其实在二叉树上来看,就是层序遍历
跟上边的基本思路是一样的,每个节点的值的计算方法是一样。只不过,我们需要借助队列来辅助我们实现。我们需要借助两个队列,一个队列存每个节点,一个队列存每个节点的数字
没从队列中取出一个结点,需要重复以下步骤
- 如果取出的结点是叶子结点,则将结点的数字累加到和中
- 如果取出的不是叶子结点,则根据当前结点的值,和子节点的值,计算出子节点对应的数字。然后将子节点和子节点对应的数字,分别放入到队列中
看代码,很好理解
代码
//广度优先搜索
func sumNumbers2(root *TreeNode) int {
if root == nil {
return 0
}
nodeQueue := []*TreeNode{root}
numQueue := []int{root.Val}
sum := 0
for len(nodeQueue) != 0 {
node := nodeQueue[0]
if len(nodeQueue) > 1 {
nodeQueue = nodeQueue[1:]
} else {
nodeQueue = []*TreeNode{}
}
num := numQueue[0]
if len(numQueue) > 1 {
numQueue = numQueue[1:]
} else {
numQueue = []int{}
}
leftNode, rightNode := node.Left, node.Right
if leftNode == nil && rightNode == nil {
sum += num
} else {
if node.Left != nil {
nodeQueue = append(nodeQueue, node.Left)
numQueue = append(numQueue, num * 10 + node.Left.Val)
}
if node.Right != nil {
nodeQueue = append(nodeQueue, node.Right)
numQueue = append(numQueue, num * 10 + node.Right.Val)
}
}
}
return sum
}
复制代码