我遇到了这个问题,其中需要从邻接列表表示中计算图的每个节点的in-degree。
for each u
for each Adj[i] where i!=u
if (i,u) ∈ E
in-degree[u]+=1
现在根据我的时间复杂性应该是O(|V||E|+|V|^2)
,但我提到的解决方案将其描述为等于O(|V||E|)
。
请帮忙告诉我哪一个是正确的。
答案 0 :(得分:7)
而不是O(| V || E |),计算indegrees的复杂性是O(| E |)。让我们考虑以下伪代码来计算每个节点的不确定性:
for each u
indegree[u] = 0;
for each u
for each v \in Adj[u]
indegree[v]++;
第一个循环具有线性复杂度O(| V |)。对于第二部分:对于每个v,最内层循环最多执行| E |时间,而最外层循环执行| V |倍。因此第二部分似乎具有复杂度O(| V || E |)。实际上,代码对每个边执行一次操作,因此更准确的复杂度是O(| E |)。
答案 1 :(得分:0)
根据http://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)Graphs.html,第4.2节,带有邻接列表表示形式,
查找节点u的前辈非常昂贵,需要在O(n + m)的时间内遍历每个节点的每个列表,其中m是边的总数。
因此,在此处使用的表示法中,计算节点的度数的时间复杂度为mergeFunction
。
但是,这可以通过使用额外空间来增加空间的方式来减少。 Wiki还指出
添加具有反向边缘的第二个图副本使我们能够找到O(d-(u))时间内u的所有前任,其中d-(u)是u的度数。
Python包Networkx是实现此方法的一个包示例。从有向图的Map.merge
对象的constructor中可以看出,O(|V| + |E|)
跟踪着DiGraph
和networkx
这两个代表继任者的字典每个节点的和前身。这样一来,它就可以有效地计算每个节点的self._succ
。
答案 2 :(得分:0)
O(|V|+|E|)
是正确的答案,因为您访问O(|V|)
中的每个顶点,并且每次访问边缘的一小部分,因此总共O(|E|)
,通常也|E|>>|V|
所以O(|E|)
也是正确的