力扣每日一题0530-1022. 从根到叶的二进制数之和

105 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。

  • 例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。

对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。

返回这些数字之和。题目数据保证答案是一个 32 位 整数。

示例 1:

image.png

输入:root = [1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22

示例 2:

输入:root = [0]
输出:0

提示:

  • 树中的节点数在 [1, 1000] 范围内
  • Node.val 仅为 0 或 1

方法一:递归

后序遍历的访问顺序为:左子树——右子树——根节点。我们对根节点 root\textit{root} 进行后序遍历:

  • 如果节点是叶子节点,返回它对应的数字 val\textit{val}
  • 如果节点是非叶子节点,返回它的左子树和右子树对应的结果之和。
var sumRootToLeaf = function(root) {
    const dfs = (root, val) => {
        if (!root) {
            return 0;
        }
        val = (val << 1) | root.val;
        if (!root.left&& !root.right) {
            return val;
        }
        return dfs(root.left, val) + dfs(root.right, val);
    }
    return dfs(root, 0);
};

复杂度分析

  • 时间复杂度:O(n),其中 n 是节点数目。总共访问 n 个节点。
  • 空间复杂度:O(n)O(n)。递归栈需要 O(n)O(n) 的空间。

方法二:迭代

我们用栈来模拟递归,同时使用一个 prev\textit{prev} 指针来记录先前访问的节点。算法步骤如下:

  1. 如果节点 root\textit{root} 非空,我们将不断地将它及它的左节点压入栈中。

  2. 我们从栈中获取节点:

    • 该节点的右节点为空或者等于 prev\textit{prev},说明该节点的左子树及右子树都已经被访问,我们将它出栈。如果该节点是叶子节点,我们将它对应的数字 val\textit{val} 加入结果中。设置 prev\textit{prev} 为该节点,设置 root\textit{root} 为空指针。
    • 该节点的右节点非空且不等于 prev\textit{prev},我们令 root\textit{root} 指向该节点的右节点。
  3. 如果 root\textit{root} 为空指针或者栈空,中止算法,否则重复步骤 1 。

需要注意的是,每次出入栈都需要更新 val\textit{val}

var sumRootToLeaf = function(root) {
    const stack = [];
    let val = 0, ret = 0;
    let prev = null;
    while (root || stack.length) {
        while (root) {
            val = (val << 1) | root.val;
            stack.push(root);
            root = root.left;
        }
        root = stack[stack.length - 1];
        if (!root.right || root.right === prev) {
            if (!root.left && !root.right) {
                ret += val;
            }
            val >>= 1;
            stack.pop();
            prev = root;
            root = null;
        } else {
            root = root.right;
        }
    }
    return ret;
};

复杂度分析

  • 时间复杂度:O(n),其中 n 是节点数目。总共访问 n 个节点。
  • 空间复杂度:O(n)。栈最多压入 n 个节点。