高频算法面试题(三十六)- 求根节点到叶节点数字之和

「这是我参与11月更文挑战的第 21 天,活动详情查看:2021最后一次更文挑战

刷算法题,从来不是为了记题,而是练习把实际的问题抽象成具体的数据结构或算法模型,然后利用对应的数据结构或算法模型来进行解题。个人觉得,带着这种思维刷题,不仅能解决面试问题,也能更多的学会在日常工作中思考,如何将实际的场景抽象成相应的算法模型,从而提高代码的质量和性能

求根节点到叶节点数字之和

题目来源LeetCode-129. 求根节点到叶节点数字之和

题目描述

给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字

每条从根节点到叶节点的路径都代表一个数字:

  • 例如,从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123

计算从根节点到叶节点生成的 所有数字之和

叶节点 是指没有子节点的节点

示例

示例 1

1.png

输入:root = [1,2,3]
输出:25
解释:
从根到叶子节点路径 1->2 代表数字 12
从根到叶子节点路径 1->3 代表数字 13
因此,数字总和 = 12 + 13 = 25
复制代码

示例 2

2.png

输入: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

解题

解法一:深度优先搜索

思路

其实这道题最容易想到的就是,如果能从左到右,或从右到左,得到每条路径上的数字就可以了,假设是从左到右,有没有发现就是前序遍历

3.png 前序遍历的思路,契合深度优先搜索的思想,就是一条路走到黑,没路了,就回退一步,找另一条路继续走下去,下边就是具体看怎么实现

首先可以发现的是,我们可以根据当前节点的值和子节点的值(左子节点或右子节点),来计算子节点表示的数字,即:子节点的数字 = 父节点的值*10 + 子节点的值

  • 如果当前结点没有子节点,也就是它本身是叶子节点,那么就可以直接返回当前节点的数字
  • 如果当前节点是非叶子节点,那它的数字,就是左右子节点数字的和

4.png 代码

// 深度优先搜索
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
}
复制代码

Guess you like

Origin juejin.im/post/7032814608884858887