Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
338 lines (269 loc) · 8.3 KB

File metadata and controls

338 lines (269 loc) · 8.3 KB
Copy raw file
Download raw file
Outline
Edit and raw actions

题目地址(129. 求根到叶子节点数字之和)

https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/

题目描述

给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。

例如,从根到叶子节点路径 1->2->3 代表数字 123。

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

说明: 叶子节点是指没有子节点的节点。

示例 1:

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

输入: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
输出: 1026
解释:
从根到叶子节点路径 4->9->5 代表数字 495.
从根到叶子节点路径 4->9->1 代表数字 491.
从根到叶子节点路径 4->0 代表数字 40.
因此,数字总和 = 495 + 491 + 40 = 1026.

前置知识

  • 递归

公司

  • 阿里
  • 百度
  • 字节

思路

这是一道非常适合训练递归的题目。虽然题目不难,但是要想一次写正确,并且代码要足够优雅却不是很容易。

这里我们的思路是定一个递归的 helper 函数,用来帮助我们完成递归操作。 递归函数的功能是将它的左右子树相加,注意这里不包括这个节点本身,否则会多加, 我们其实关注的就是叶子节点的值,然后通过层层回溯到 root,返回即可。

整个过程如图所示:

129.sum-root-to-leaf-numbers-1

那么数字具体的计算逻辑,如图所示,相信大家通过这个不难发现规律:

129.sum-root-to-leaf-numbers-2

关键点解析

  • 递归分析

代码

  • 语言支持:JS,C++,Python, Go, PHP

JS Code:

/*
 * @lc app=leetcode id=129 lang=javascript
 *
 * [129] Sum Root to Leaf Numbers
 */
function helper(node, cur) {
  if (node === null) return 0;
  const next = node.val + cur * 10;

  if (node.left === null && node.right === null) return next;

  const l = helper(node.left, next);
  const r = helper(node.right, next);

  return l + r;
}
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var sumNumbers = function (root) {
  // tag: `tree` `dfs` `math`
  return helper(root, 0);
};

C++ Code:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int sumNumbers(TreeNode* root) {
        return helper(root, 0);
    }
private:
    int helper(const TreeNode* root, int val) {
        if (root == nullptr) return 0;
        auto ret = root->val + val * 10;
        if (root->left == nullptr && root->right == nullptr)
            return ret;
        auto l = helper(root->left, ret);
        auto r = helper(root->right, ret);
        return l + r;
    }
};

Python Code:

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def sumNumbers(self, root: TreeNode) -> int:

        def helper(node, cur_val):
            if not node: return 0
            next_val = cur_val * 10 + node.val

            if not (node.left or node.right):
                return next_val

            left_val = helper(node.left, next_val)
            right_val = helper(node.right, next_val)

            return left_val + right_val

        return helper(root, 0)

Go Code:

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumNumbers(root *TreeNode) int {
	return helper(root, 0)
}

func helper(root *TreeNode, cur int) int {
	if root == nil {
		return 0 // 当前非叶子节点, 不计算
	}

	next := cur*10 + root.Val
	if root.Left == nil && root.Right == nil {
		return next // 当前为叶子节点, 计算
	}

	l := helper(root.Left, next)
	r := helper(root.Right, next)
	return l + r
}

PHP Code:

/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     public $val = null;
 *     public $left = null;
 *     public $right = null;
 *     function __construct($value) { $this->val = $value; }
 * }
 */
class Solution
{

    /**
     * @param TreeNode $root
     * @return Integer
     */
    function sumNumbers($root)
    {
        return (new Solution())->helper($root, 0);
    }

    /**
     * @param TreeNode $root
     * @param int $cur
     * @return int
     */
    function helper($root, $cur)
    {
        if (!$root) return 0; // 当前不是叶子节点
        $next = $cur * 10 + $root->val;
        if (!$root->left && !$root->right) return $next; // 当前为叶子节点, 返回叶子节点的值

        $l = (new Solution())->helper($root->left, $next);
        $r = (new Solution())->helper($root->right, $next);
        return $l + $r;
    }
}

复杂度分析

  • 时间复杂度:$O(N)$
  • 空间复杂度:$O(N)$

拓展

通常来说,可以利用队列、栈等数据结构将递归算法转为递推算法。

描述

使用两个队列:

  1. 当前和队列:保存上一层每个结点的当前和(比如 49 和 40)
  2. 结点队列:保存当前层所有的非空结点

每次循环按层处理结点队列。处理步骤:

  1. 从结点队列取出一个结点
  2. 从当前和队列将上一层对应的当前和取出来
  3. 若左子树非空,则将该值乘以 10 加上左子树的值,并添加到当前和队列中
  4. 若右子树非空,则将该值乘以 10 加上右子树的值,并添加到当前和队列中
  5. 若左右子树均为空时,将该节点的当前和加到返回值中

实现

  • 语言支持:C++,Python

C++ Code:

class Solution {
public:
    int sumNumbers(TreeNode* root) {
        if (root == nullptr) return 0;
        auto ret = 0;
        auto runningSum = vector<int>{root->val};
        auto queue = vector<const TreeNode*>{root};
        while (!queue.empty()) {
            auto sz = queue.size();
            for (auto i = 0; i < sz; ++i) {
                auto n = queue.front();
                queue.erase(queue.begin());
                auto tmp = runningSum.front();
                runningSum.erase(runningSum.begin());
                if (n->left != nullptr) {
                    runningSum.push_back(tmp * 10 + n->left->val);
                    queue.push_back(n->left);
                }
                if (n->right != nullptr) {
                    runningSum.push_back(tmp * 10 + n->right->val);
                    queue.push_back(n->right);
                }
                if (n->left == nullptr && n->right == nullptr) {
                    ret += tmp;
                }
            }
        }
        return ret;
    }
};

Python Code:

class Solution:
    def sumNumbers(self, root: TreeNode) -> int:
        if not root: return 0
        result = 0
        node_queue, sum_queue = [root], [root.val]
        while node_queue:
            for i in node_queue:
                cur_node = node_queue.pop(0)
                cur_val = sum_queue.pop(0)
                if cur_node.left:
                    node_queue.append(cur_node.left)
                    sum_queue.append(cur_val * 10 + cur_node.left.val)
                if cur_node.right:
                    node_queue.append(cur_node.right)
                    sum_queue.append(cur_val * 10 + cur_node.right.val)
                if not (cur_node.left or cur_node.right):
                    result += cur_val
        return result

相关题目

这道题和本题太像了,跟一道题没啥区别

大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。

Morty Proxy This is a proxified and sanitized view of the page, visit original site.