算法思想一:深度优先搜索
解题思路:
二叉树的每条从根节点到叶子节点的路径都代表一个数字。其实,每个节点都对应一个数字,等于其父节点对应的数字乘以 10 再加上该节点的值(这里假设根节点的父节点对应的数字是 0)。只要计算出每个叶子节点对应的数字,然后计算所有叶子节点对应的路径之和,即可得到结果
深度优先搜索是很直观的做法。从根节点开始,遍历每个节点,如果遇到叶子节点,则将叶子节点对应的数字加到路径之和。如果当前节点不是叶子节点,则计算其子节点对应的数字,然后对子节点递归遍历。
图解:
代码展示:
Python版本
class Solution: def sumNumbers(self , root ): # write code here def dfs(root, prevTotal): if not root: return 0 total = prevTotal * 10 + root.val if not root.left and not root.right: # 到达叶子结点,返回结果 return total else: # 对左右子树进行递归 return dfs(root.left, total) + dfs(root.right, total) # 深度搜索 return dfs(root, 0)
复杂度分析:
时间复杂度:O(N),其中 N 是二叉树的节点个数。对每个节点访问一次。空间复杂度:O(N),其中 N 是二叉树的节点个数。空间复杂度主要取决于递归调用的栈空间,递归栈的深度等于二叉树的高度,最坏情况下,二叉树的高度等于节点个数,空间复杂度为 O(N)。
算法思想二:深度优先搜索
解题思路:
使用广度优先搜索,需要维护两个队列,分别存储节点和节点对应的数字。
1、初始时,将根节点和根节点的值分别加入两个队列。每次从两个队列分别取出一个节点和一个数字,进行如下操作:
如果当前节点是叶子节点,则将该节点对应的数字加到路径之和;
如果当前节点不是叶子节点,则获得当前节点的非空子节点,并根据当前节点对应的数字和子节点的值计算子节点对应的数字,然后将子节点和子节点对应的数字分别加入两个队列。
2、搜索结束后,即可得到所有叶子节点对应的路径之和。
1、初始时,将根节点和根节点的值分别加入两个队列。每次从两个队列分别取出一个节点和一个数字,进行如下操作:
如果当前节点是叶子节点,则将该节点对应的数字加到路径之和;
如果当前节点不是叶子节点,则获得当前节点的非空子节点,并根据当前节点对应的数字和子节点的值计算子节点对应的数字,然后将子节点和子节点对应的数字分别加入两个队列。
2、搜索结束后,即可得到所有叶子节点对应的路径之和。
图解:
代码展示:
JAVA版本
public class Solution { /** * * @param root TreeNode类 * @return int整型 */ public int sumNumbers (TreeNode root) { // write code here if (root == null) { return 0; } int sum = 0; // 定义结点队列 QueuenodeQueue = new LinkedList(); // 定义到达该结点时 数字 队列 QueuenumQueue = new LinkedList(); // 根节点先进队列 nodeQueue.offer(root); numQueue.offer(root.val); while (!nodeQueue.isEmpty()) { TreeNode node = nodeQueue.poll(); int num = numQueue.poll(); TreeNode left = node.left, right = node.right; if (left == null && right == null) { sum += num; } else { if (left != null) { nodeQueue.offer(left); numQueue.offer(num * 10 + left.val); } if (right != null) { nodeQueue.offer(right); numQueue.offer(num * 10 + right.val); } } } return sum; } }
复杂度分析:
时间复杂度:O(N),其中 N 是二叉树的节点个数。对每个节点访问一次。空间复杂度:O(N),其中 N 是二叉树的节点个数。空间复杂度主要取决于队列,每个队列中的元素个数不会超过 N