📜  二叉树中任何路径的1的计数(1)

📅  最后修改于: 2023-12-03 15:06:19.814000             🧑  作者: Mango

二叉树中任何路径的1的计数

在二叉树中,我们可以通过遍历每个节点并选择一个路径来构建一条路径。一条路径定义为从一个起始节点开始,沿着连接到另一个节点的边行进,直到到达一个终止节点,后者没有任何连出边。

针对本题,我们需要计算二叉树中任何一条路径上数字1的个数。

解题思路
递归

一种直接的方法是使用递归。我们可以通过递归遍历整个二叉树,计算每个路径上数字1的个数,最终将它们相加即可得到答案。

具体来说,对于每个节点,我们可以计算它的左子树和右子树中任何一条不包含该节点的路径中数字1的个数,再加上包含该节点的路径中数字1的个数。令左子树中尝试不包含该节点的路径的数字1的个数为 $L$,右子树中尝试不包含该节点的路径的数字1的个数为 $R$,包含该节点的路径中数字1的个数为 $C$,则该节点对答案的贡献为 $C = L + R + 1$。我们可以从根节点开始递归,直到遍历到叶子节点为止。

回溯法

我们还可以使用回溯法来解决本题。回溯法通常适用于求解所有可能路径的问题。对于二叉树中的每一条路径,我们都可以通过回溯法遍历它,统计其中数字1的个数,并将它们相加即可得到答案。

具体来说,我们可以从根节点开始递归,对于每个节点,我们可以将它加入当前路径中,计算当前路径中数字1的个数,然后分别递归遍历它的左子树和右子树,并分别计算它们的贡献。在递归完成后,我们需要将该节点从当前路径中移除,以便继续搜索其他可能路径。

代码示例
递归
class Solution:
    def countPaths(self, root: TreeNode) -> int:
        self.ans = 0  # 存储答案
        self.dfs(root)
        return self.ans
    
    def dfs(self, node: TreeNode) -> int:
        if not node:
            return 0
        left = self.dfs(node.left)  # 左子树中不包含该节点的路径中数字1的个数
        right = self.dfs(node.right)  # 右子树中不包含该节点的路径中数字1的个数
        cnt = node.val == 1  # 包含该节点的路径中数字1的个数
        self.ans += cnt + left + right  # 更新答案
        return cnt + max(left, right)  # 返回包含该节点的路径中数字1的个数
回溯法
class Solution:
    def countPaths(self, root: TreeNode) -> int:
        self.ans = 0  # 存储答案
        path = []  # 存储当前路径
        self.dfs(root, path)
        return self.ans
    
    def dfs(self, node: TreeNode, path: List[int]) -> None:
        if not node:
            return
        path.append(node.val)  # 将该节点加入当前路径
        cnt = path.count(1)  # 统计当前路径中数字1的个数
        self.ans += cnt  # 更新答案
        self.dfs(node.left, path)  # 递归遍历左子树
        self.dfs(node.right, path)  # 递归遍历右子树
        path.pop()  # 将该节点从当前路径中移除,以便继续搜索其他可能路径