leetcode
leetcode 951 ~ 1000
从根到叶的二进制数之和

从根到叶的二进制数之和

难度:

标签:

题目描述

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

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

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

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

 

示例 1:

输入: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 仅为 01 

代码结果

运行时间: 23 ms, 内存: 0.0 MB


/*
 * 思路:
 * 1. 使用Java Stream的方式计算从根到叶子的路径的值。
 * 2. 我们需要对每个路径计算其二进制数,并累加这些值。
 */

import java.util.stream.Stream;
import java.util.stream.IntStream;

public class Solution {
    public int sumRootToLeaf(TreeNode root) {
        return sum(root, 0);
    }

    private int sum(TreeNode node, int currentSum) {
        if (node == null) {
            return 0;
        }
        currentSum = (currentSum << 1) | node.val;
        if (node.left == null && node.right == null) {
            return currentSum;
        }
        return Stream.of(node.left, node.right)
                     .flatMapToInt(n -> IntStream.of(sum(n, currentSum)))
                     .sum();
    }
}

// TreeNode类定义
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

解释

方法:

该题解采用了迭代的深度优先搜索(DFS)方法来解决问题。首先,如果根节点为空,则直接返回0。对于非空的树,使用一个栈来存储需要遍历的节点及其对应的当前二进制数值。栈的初始化包含根节点和其值。在遍历过程中,每次从栈中弹出一个元素,检查是否为叶子节点(即左右子树都为空)。如果是叶子节点,则将当前的二进制数值加到结果中。如果不是叶子节点,则对其非空的子节点进行处理,将子节点以及对应的更新后的二进制数值(当前值左移一位加上子节点的值,即currVal * 2 + currTree.child.val)压入栈中。这个过程重复直到栈为空,最后返回累加的结果。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么选择使用迭代的深度优先搜索(DFS)而不是递归的DFS方法来解决这个问题?
迭代的DFS使用显式的栈来控制遍历过程,这样可以避免递归造成的栈溢出问题,特别是在处理非常深的树时更加安全。此外,迭代方法可以让内存使用更加可控,易于调试和理解,尤其是在复杂的二进制数处理中。
🦆
在处理二进制数累加时,是否有可能出现整数溢出,特别是当树的深度接近或等于32时?
确实有可能出现整数溢出的情况。Python 的整数类型在内部会自动转为长整型来处理大数,因此在Python中不会产生传统意义上的溢出错误,但在其他一些语言中,如Java或C++,可能需要特别处理,比如使用长整形数据类型或者在每次累加后进行模运算以避免溢出。
🦆
如何确保在从栈中弹出的元素都正确地表示从根到当前节点的路径的二进制数值?
在迭代过程中,每个栈元素都包含当前节点以及从根到该节点的累积二进制数值。每当访问一个节点时,我们根据其父节点的二进制数值计算当前节点的二进制数值(左移并加上当前节点值)。这种方法确保了每次从栈中弹出的元素都能准确地反映从根节点到当前节点的完整路径值。
🦆
题解中提到,如果节点不是叶子节点则继续处理其子节点。如果当前节点的左或右子节点为null,应如何处理以保持算法的正确性?
如果一个节点的左或右子节点为null,这意味着这个方向没有子树,因此在处理时只需将非null的子节点和对应的二进制数值推入到栈中。具体来说,如果左子节点为null,只处理右子节点;如果右子节点为null,只处理左子节点。这样保证了只有存在的路径被考虑进最终的累加结果。

相关问题