问题描述
所以假设问题是计算二叉树中的路径数,其总和等于某个目标。
一种简单的方法是为每个子节点递归调用 DFS 两次,一次用于将子节点用于在其之前某处开始的路径,另一次用于开始搜索从子节点开始的路径。
这种方法的时间复杂度为 O(4^k),其中 k 是树的高度,但是相对于节点数的复杂度是多少 n 在树上?
我知道常规 DFS 的时间复杂度为 O(n),因为它只访问每个树节点一次,但是如果我没记错的话,这种方法将访问 m 级节点 2^m 次.
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(?))