DFS 复杂性,对二叉树中的每个子节点进行两次递归调用

问题描述

所以假设问题是计算二叉树中的路径数,其总和等于某个目标。

一种简单的方法是为每个子节点递归调用 DFS 两次,一次用于将子节点用于在其之前某处开始的路径,另一次用于开始搜索从子节点开始的路径。

这种方法的时间复杂度为 O(4^k),其中 k 是树的高度,但是相对于节点数的复杂度是多少 n 在树上?

我知道常规 DFS 的时间复杂度为 O(n),因为它只访问每个树节点一次,但是如果我没记错的话,这种方法将访问 m 级节点 2^m 次.

这是我在python中解决问题的代码

def cnt_paths(root,target):
    return dfs(root,target,set())


def dfs(node,current_sum,visited):
    cnt = 0
    if current_sum + node.val == target:
        cnt += 1

    if node.left:
        cnt += dfs(node.left,current_sum + node.val,visited)  # include this node
        if node.left not in visited:
            cnt += dfs(node.left,visited)  # start from scratch on next node
            visited.add(node.left)

    if node.right:
        cnt += dfs(node.right,visited)
        if node.right not in visited:
            cnt += dfs(node.right,visited)
            visited.add(node.right)

    return cnt

解决方法

无需深入研究您的代码,如果您确实已经知道它的时间复杂度是 O(4k) 对于树高度 k >,那么我们也可以求出节点数的复杂度。

高度k的二叉树有n = O(2^k)个节点,因此,

O(4k) = O(4log2(n)) = O(22 * log2(n)) = O((2log2(n))2)= O(n2).

,

您列出的复杂性不正确。如果一个节点的深度是 d,那么该节点与 d 不同的和的起点(根,根的子节点,...节点的父节点或节点本身)。换句话说,表达式 current_sum + node.val 针对特定的 node(但具有不同的 current_sum 值)被计算 d 次。

这意味着您总共拥有此类操作的 SUM[depth(node)]。在一个完美的二叉树中,这个和是:

1 + 2*2 + 3*4 + 4*8 + ... + ?2?-1

其中 ? 是树的高度。这个总和小于

?∑?=1..?2?-1

等于?(2?-1),即

O(?2?)

高度为?的完美二叉树的节点数?为?=2?,所以操作数,改写为?为:

O(?log(?))