LeetCode 1022. 从根到叶的二进制数之和
题目描述



题意分析
每个节点值是二进制位
0或1,一条从根到叶的路径按经过顺序组成一个二进制整数,根是最高位,叶子是最低位。要求把所有完整路径对应的数值相加。路径上的位需要按位置拼接,不是把节点值简单相加。只有左右孩子都为空才是叶子;到达内部节点时得到的只是数字前缀,不能提前计入总和。
解法:DFS 累积路径值
核心思路
[!blue]
已有二进制数值末尾追加一位,相当于让原来的每一位向左移动,再把新位填到最低位。因此从路径前缀
prefix到当前节点的数值是prefix * 2 + node.val,也可以写成(prefix << 1) | node.val,左移后的最低位为零,所以按位或正好等价于加入这一位。定义递归参数
prefix为从根到当前节点父亲形成的数值,尚未包含当前位。进入节点后先计算value,它才是根到当前节点的完整前缀。空节点代表这侧没有路径,贡献为
0;叶子代表一条路径已经完成,返回value;非叶子则把value分别传给左右孩子,再将两侧的完整路径贡献相加。左右子树的路径集合互不重叠,合并后恰好包含当前节点之下的全部根到叶路径。从根前的空前缀
0开始。整数参数按值传递,左分支的更新不会改动右分支要使用的前缀,因此无需构造字符串,也不需要共享可变路径或额外回滚。
解题步骤
- 调用
dfs(root, 0),空节点直接返回0。- 当前节点存在时,左移前缀并加入当前二进制位,得到
value。- 若左右孩子都为空,返回这一条完整路径的数值。
- 否则用同一个
value递归两侧,返回左右结果之和。
代码实现
class Solution {
public int sumRootToLeaf(TreeNode root) {
return dfs(root, 0);
}
// prefix 表示根到父节点的路径值,尚未包含当前节点。
private int dfs(TreeNode node, int prefix) {
// 空孩子没有完整路径,对总和贡献为零。
if (node == null) {
return 0;
}
// 左移一位后加入当前位,得到根到当前节点的二进制数。
int value = (prefix << 1) | node.val;
// 只有原树中的叶子才对应一条完整路径。
if (node.left == null && node.right == null) {
return value;
}
return dfs(node.left, value) + dfs(node.right, value);
}
}
func sumRootToLeaf(root *TreeNode) int {
var dfs func(*TreeNode, int) int
// prefix 表示根到父节点的路径值,尚未包含当前节点。
dfs = func(node *TreeNode, prefix int) int {
// 空孩子没有完整路径,对总和贡献为零。
if node == nil {
return 0
}
// 左移一位后加入当前位,得到根到当前节点的二进制数。
value := (prefix << 1) | node.Val
// 只有原树中的叶子才对应一条完整路径。
if node.Left == nil && node.Right == nil {
return value
}
return dfs(node.Left, value) + dfs(node.Right, value)
}
return dfs(root, 0)
}
复杂度分析
- 时间复杂度:$O(n)$,每个节点访问一次。
- 空间复杂度:$O(h)$,h 为树高,来自递归栈。
关键点总结
[!green]
- 左移再加当前位体现二进制位权,路径越深,已有前缀的位权继续提高。
- 参数传递一条路径的前缀,返回值汇总这棵子树下的完整路径,两者含义不同。
- 空子树不产生路径,叶子才结算,中间节点只负责扩展并合并。
易错点总结
[!yellow]
- 用节点值直接相加,会丢掉根到叶顺序对应的二进制位权。
- 先按位或再左移,会把新加入的最低位也整体左移,得到错误数值。
- 任意一个孩子为空就判为叶子,会提前停止只有单侧孩子的路径。
- 每进入一个节点都累加当前前缀,会把未结束的短路径也加入答案。
- 给孩子继续传旧
prefix而不是value,会漏掉当前节点的位。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 129. 求根节点到叶节点数字之和 | 中等 | 根到叶数值累积相同,本题每层乘2加当前位,原题每层乘10。 |
| 112. 路径总和 | 简单 | 同样遍历根到叶路径,但本题路径状态是按位形成的数,不是简单的节点和。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!