目录

题目描述

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

image-20230305193838019

image-20230305193843947

题意分析

每个节点存一个一位数字,从根走到某个叶子的路径按经过顺序拼成一个十进制整数,要求返回所有这类整数的总和。注意求的是,不是路径列表,所以不需要把路径本身保留下来。

「节点值是一位数字」这个条件直接给出了拼接的算法信号:在一位数的前提下,「在已有数字后面接一位」就等价于「乘 10 再加上这一位」,于是路径数字可以自顶向下增量维护。题面还保证结果落在 32 位整数范围内,因此可以放心用 int 累加,不必考虑溢出。

「叶子」的定义是左右孩子都为空的节点,只有它才对应一条完整路径。这一点是本题绝大多数错误的来源:走到中途的节点,其路径数字只是一个前缀,不能结算。

边界情形有三类:整棵树只有一个节点,此时根同时也是叶子,答案就是根的值;某个节点只有一个孩子,它不是叶子,既不能在这里结算,也不能把它的空孩子当成叶子;路径上可以出现值为 0 的节点,4 → 0 → 5 拼出来的是 405,任何「跳过 0」的处理都是错的。

解法:DFS 传递路径数值

核心思路

深度优先遍历时,用 current = prefix * 10 + node.val 把当前节点拼到路径数字末尾。只有叶子节点代表一条完整路径,此时返回 current;非叶子节点返回左右子树结果之和。

解题步骤

  • 从根节点开始 DFS,初始路径值为 0
  • 到达节点后计算 current = prefix * 10 + node.val
  • 若当前节点是叶子,返回 current
  • 否则将 current 传给左右孩子,并把两侧结果相加。

代码实现

class Solution {
    public int sumNumbers(TreeNode root) {
        return dfs(root, 0);
    }

    private int dfs(TreeNode node, int prefix) {
        if (node == null) {
            return 0;
        }

        int current = prefix * 10 + node.val;
        if (node.left == null && node.right == null) {
            return current;
        }

        return dfs(node.left, current) + dfs(node.right, current);
    }
}
func sumNumbers(root *TreeNode) int {
    var dfs func(*TreeNode, int) int
    dfs = func(node *TreeNode, prefix int) int {
        if node == nil {
            return 0
        }

        current := prefix*10 + node.Val
        if node.Left == nil && node.Right == nil {
            return current
        }

        return dfs(node.Left, current) + dfs(node.Right, current)
    }

    return dfs(root, 0)
}

复杂度分析

  • 时间复杂度:$O(n)$,每个节点访问一次。
  • 空间复杂度:$O(h)$,h 为树高,来自递归栈。

关键点总结

  • 路径数字可增量计算,无需保存完整路径。
  • 只有左右孩子都为空的节点才是叶子。
  • 空子树返回 0,便于直接相加左右结果。

易错点总结

  • 在非叶子节点累加路径值,会把不完整路径计入答案。
  • 递归孩子时必须传 current,不能继续传旧的 prefix
  • 叶子判断必须同时检查左右孩子,只有一个孩子的节点不是叶子。

相似题目

题目 难度 考察点
112. 路径总和 简单 只问存在性,找到第一条满足的路径就能短路返回,不必把整棵树走完
113. 路径总和 II 中等 要求返回路径本身,前缀信息不再可压缩成一个数,必须维护可变 path、撤销并拷贝快照
257. 二叉树的所有路径 简单 前缀是字符串而非数字,拼接不可逆,因此更适合每层传一份新副本而不是共享缓冲区
404. 左叶子之和 简单 结算条件除了「是叶子」还要看它挂在父节点的哪一侧,判断必须放到父层去做
1022. 从根到叶的二进制数之和 简单 同一套增量公式把基数从 10 换成 2,可以直接用左移加或运算代替乘加
LCR 049. 求根节点到叶节点数字之和 中等 与本题同题换皮,适合用来检验参数不变量与返回值语义能否脱稿说清
剑指 Offer 34. 二叉树中和为某一值的路径 中等 目标和固定且要输出全部路径,等价于 113 题,重点转移到回溯的撤销与快照上