今天我和我的老板讨论了我的代码的顺序,但我们无法就代码的时间复杂性达成一致。我相信我的代码是O(n)
,但我的老板不接受。
您对此代码的顺序有何看法?
void Process(Node currentNode)
{
Print(currentNode.Title); //O(Print)=O(1)
foreach(Child child in currentNode.Children)
{
Process(child);
}
}
EDIT1
多个Node
s不共享同一个孩子Node
。我有一棵树。
Children
是Node
的简单列表,因此可以在班轮时间内轻松访问其成员。
您可以在此处看到Node
class:
class Node
{
public string Title{get;set;}
public List<Node> Children{get;set}
}
答案 0 :(得分:8)
如果这是a tree而n
是树中的节点数...
然后是的,它是O(n)
。
很容易看出我们每个节点只做一定量的工作。
每个节点只是另一个节点的子节点,因此它只出现在for循环中一次。由于for循环迭代(不包括递归调用)需要O(1)
,我们可以看到递归的for循环部分(对于所有调用)都接受O(n)
。而且函数的其余部分显然是O(1)
,并且从树的定义中,我们可以看到我们每个节点只执行一次函数,因此O(n)
次。
因此总运行时间为O(n)
。
注意:我假设Children
是可以在线性时间内枚举的东西。如果不是这样,则运行时间与枚举它所需的时间相同。更具体地说,最坏的情况是当一个节点具有剩余的n-1
节点作为子节点(并且没有其他节点具有子节点)。我认为这样做的证明会分散注意力,所以我会把它留下一天。
如果它不是树,即多个节点可以有相同的孩子,或者有一个周期,那么它不是O(n)
。在循环的情况下,它不会终止。如果多个节点可以拥有相同的子节点,但是没有一个循环,则运行时间将是指数级的 - 根节点可以有n-1
个子节点。其中一个孩子可以有n-2
个孩子,其中一个可以有n-3
个孩子等。
答案 1 :(得分:3)
我认为时间顺序是O(N),其中N是你Process
元素后代的总数。这是因为对于每个后代,你Print
。如果你执行O(1)任务N次,那就是O(N)。
答案 2 :(得分:3)
这实际上取决于currentNode.Children
实际实现的方式(或底层支持数据结构是什么)。
.Children
可以很容易地成为一个属性,它返回自己的枚举器及其自己的实现,时间复杂度只取决于自定义枚举器算法。
从表面上看,它看起来可能是O(N)
,但在.Children
属性后面定义/实现,应该可以给出更明确的答案。在这一点上,没有足够的信息可以明确地说出来。