1. 问题背景与理解
今天遇到一道挺有意思的二叉树题目 - LeetCode 1022,要求计算从根节点到叶节点的所有路径表示的二进制数之和。初次看到这个题目时,我意识到这需要结合二叉树的遍历和二进制数的处理技巧。
这类题目在实际面试中经常出现,因为它能同时考察候选人对数据结构的掌握和对基础算法的运用能力。我在准备面试时发现,类似的问题在Google和Facebook的面试题库中出现频率很高。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题详细解析
2.1 题目要求
给定一个二叉树,每个节点的值都是0或1。每条从根到叶的路径代表一个二进制数,最高位在根节点,最低位在叶节点。我们需要计算所有这些二进制数之和。
例如:
code复制 1
/ \
0 1
/ \ / \
0 1 0 1
这个树有4条路径:
- 1->0->0 = 100(4)
- 1->0->1 = 101(5)
- 1->1->0 = 110(6)
- 1->1->1 = 111(7)
总和为4+5+6+7=22
2.2 解题思路分析
看到这个问题,我首先想到的是需要遍历所有从根到叶的路径。这自然让我联想到深度优先搜索(DFS)算法。DFS特别适合处理这种需要探索所有可能路径的问题。
对于每条路径,我们需要:
- 从根节点开始,记录当前路径的值
- 遇到子节点时,将当前值左移一位(相当于乘以2),然后加上子节点的值
- 到达叶节点时,将完整的二进制数加入总和
3. 算法实现细节
3.1 递归解法
递归是最直观的实现方式。我们可以定义一个辅助函数,它接收当前节点和当前路径值作为参数。
python复制def sumRootToLeaf(root):
def dfs(node, current_sum):
if not node:
return 0
current_sum = (current_sum << 1) | node.val
if not node.left and not node.right:
return current_sum
return dfs(node.left, current_sum) + dfs(node.right, current_sum)
return dfs(root, 0)
这个实现有几个关键点:
current_sum << 1相当于乘以2,为新的二进制位腾出空间| node.val将当前节点的值加到最低位- 只有到达叶节点时才返回当前路径值,否则继续递归
3.2 迭代解法
虽然递归解法简洁,但在实际面试中,面试官可能会要求迭代实现。我们可以使用栈来模拟递归过程:
python复制def sumRootToLeaf(root):
if not root:
return 0
stack = [(root, 0)]
total = 0
while stack:
node, current_sum = stack.pop()
current_sum = (current_sum << 1) | node.val
if not node.left and not node.right:
total += current_sum
else:
if node.right:
stack.append((node.right, current_sum))
if node.left:
stack.append((node.left, current_sum))
return total
迭代解法的优势是避免了递归的栈溢出风险,特别适合处理深度很大的树。
4. 复杂度分析
4.1 时间复杂度
两种解法的时间复杂度都是O(N),其中N是树中节点的数量。因为我们需要访问每个节点一次。
4.2 空间复杂度
递归解法在最坏情况下(树退化为链表)的空间复杂度是O(N),因为递归调用栈的深度等于树的高度。
迭代解法在最坏情况下也是O(N),因为栈中最多需要存储与树高度成比例的节点数。
5. 优化与变种
5.1 路径压缩技巧
在实际实现中,我们可以利用位运算的特性来优化计算。注意到:
code复制current_sum = (current_sum << 1) | node.val
这行代码高效地实现了二进制数的构建,避免了字符串操作等开销较大的方法。
5.2 相关问题变种
这个问题有几个有趣的变种:
- 如果节点值不只是0和1,而是任意数字怎么办?
- 如果要求的是路径表示的十进制数之和呢?
- 如果要求找出和最大的路径而不是所有路径的和?
这些变种可以帮助我们更深入地理解这类问题的本质。
6. 常见错误与调试技巧
6.1 常见错误
- 忘记处理空树的情况
- 在非叶节点就累加路径值
- 位运算操作顺序错误
- 递归终止条件不完整
6.2 调试技巧
- 先在小树上手动计算预期结果
- 打印中间路径值验证计算过程
- 使用可视化工具观察树的遍历顺序
- 对于递归解法,可以添加打印语句显示递归深度和当前状态
7. 实际应用场景
虽然这个问题看起来是纯算法题,但它有实际的应用背景:
- 文件系统路径的权限管理
- 网络路由表的匹配算法
- 决策树的路径评估
- 遗传算法的染色体表示
理解这类问题的解法可以帮助我们在实际工程中更好地处理树形结构的遍历和计算问题。
8. 个人解题心得
在解决这个问题时,我最初尝试了先收集所有路径再计算的方法,发现效率不高。后来意识到可以在遍历过程中动态计算路径值,大大简化了代码。
另一个收获是认识到位运算在这种二进制相关问题中的强大作用。相比字符串处理或数学计算,位运算通常更高效且简洁。
最后,我建议在面试准备时,不仅要能写出解法,还要能清晰解释每一步的意图和背后的思考过程。这往往比单纯的代码实现更能展示你的问题解决能力。
