【问题标题】:Why is time complexity for BFS/DFS not simply O(E) instead of O(E+V)?为什么 BFS/DFS 的时间复杂度不仅仅是 O(E) 而不是 O(E+V)?
【发布时间】:2015-01-01 05:42:33
【问题描述】:

我知道堆栈溢出有一个类似的问题,有人问,为什么 BFS/DFS 的时间复杂度不只是 O(V)。

给出的适当答案是,在完整图的情况下,E 可以与 V^2 一样大,因此将 E 包含在时间复杂度中是有效的。

但是,如果 V 不能大于 E+1。那么,在那种情况下,时间复杂度没有 V,应该可行吗?

【问题讨论】:

  • 更多人应该有这个问题 tbh

标签: graph time-complexity depth-first-search breadth-first-search


【解决方案1】:

如果给定E = kV + c,对于一些实常数kc 那么,
O(E + V) = O(kV + c + V) = O(V) = O(E) 并且你的论点是正确的。

树就是一个例子。

一般而言(即,没有任何先验信息),但是,E = O(V^2),因此我们不能比O(V^2)做得更好。

为什么不总是只写 O(E)?

编辑:总是写O(E + V) 的主要原因是为了避免歧义。

例如,可能存在图中根本没有边的情况(即O(E) ~ O(1))。即使在这种情况下,我们也必须前往每个顶点 (O(V)),我们无法在 O(1) 时间内完成。

因此,一般只写O(E) 是不行的。

【讨论】:

  • 那么,我可以简单地说 O(E) 作为 BFS 的时间复杂度吗?
  • @Sandy 仅在满足上述条件时。在一般情况下,可能没有边,但你仍然必须去每个顶点,因此我们写O(V + E)
  • 当你无法通过边找到它们时,你将如何“去每个顶点”?这个答案不正确。
  • @MattTimmermans for source in V: dfs(source)。在|E| = 0 的图中,这个循环的时间复杂度是多少?
  • @axiom 没有人询问从每个可能的顶点运行搜索。
【解决方案2】:

必须包含 V,因为 BFS 和 DFS 都依赖于大小为 |V| 的数组。跟踪哪些顶点已被处理/发现/探索(无论情况如何)。如果一个图有 0 条边和 100000 个顶点,那么与只有 5 个顶点的情况相比,这样的数组仍然需要更多的时间来初始化。因此,BFS 和 DFS 的时间复杂度在 |V| 上扩展。

【讨论】:

  • 您可以使用哈希表而不是数组来实现 BFS 或 DFS,因此初始化需要 O(1) 时间而不是 O(V)。
  • 你的意思是把每个顶点插入到哈希表中(即把它用作从顶点到布尔值的无序映射)?
  • 哈希表中的键是访问过的顶点;当且仅当它存在于哈希表中时才会访问顶点。这样,您可以从一个空的哈希表开始(即尚未访问任何顶点),并且您不必将每个顶点显式标记为“尚未访问”。我认为哈希表是无序集而不是地图的实现,但是如果有不同的状态(例如,访问前与访问后),那么地图可能会更有用。
  • @kaya3 你的哈希表有多大?你初始化了吗? :) OK OK,如果您使用动态增长的哈希表,那么 BFS 的复杂性预计为 O(E) 而不是 O(V+E)。这不是通常的实现,而且有充分的理由。
  • @MattTimmermans 如果您使用的是用于内置集合类型的数据结构的高级语言编写,那么使用动态增长的哈希表来实现 BFS 和 DFS 是很常见的。例如,“深度优先搜索 python”的前三个 Google 结果中的两个初始化visited = set(),链接herehere
猜你喜欢
  • 2012-07-13
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 2019-01-29
  • 1970-01-01
  • 2021-02-15
  • 1970-01-01
  • 2017-12-26
相关资源
最近更新 更多