【问题标题】:Big O Running Time for different Data Strucutres不同数据结构的大 O 运行时间
【发布时间】:2011-08-12 13:50:27
【问题描述】:

我试图想出以下数据结构的大 O 运行时间。 他们正确吗?

  • 将 n 个整数插入到最初为空的 AVL 树中(最佳情况) O(log n)

  • 将 n 个整数插入到最初为空的 AVL 树中(最坏情况) O(log n)

  • 将 n 个整数插入最初为空的二叉搜索树中,该二叉搜索树不强制执行 结构特性(最佳情况) O(log n)

  • 将 n 个整数插入最初为空的二叉搜索树中,该二叉搜索树不强制执行 结构特性(最坏情况) O(n)

解释为什么它们不正确也会很有帮助

【问题讨论】:

  • 为什么这个标签是 C ?所有语言的复杂性肯定是一样的吗?
  • 您的意思是插入每个元素需要多少时间?还是全部?插入 n 个元素始终是 omega(n)。
  • @cnicutar:严格来说,复杂度取决于基本操作的复杂度。 C 中的基本操作与 Haskell 或 Prolog 中的不同。不过,在这种情况下,这并不重要。
  • @amit 这不一定是真的。使用分布式计算和共享内存,在插入单个元素的同时插入 n 个元素是完全可行的。虽然它可能不一定适用于这种情况,但请务必注意。
  • @glowcoder:时间复杂度是指需要的 OP 数量,而不是实际花费的时间。它仍然需要 omega(n) OP,只是碰巧它们同时发生。

标签: data-structures big-o time-complexity


【解决方案1】:

我在这里假设您需要插入所有元素的总时间:

(1) 在 AVL 树的最佳情况,您将永远不需要低于根,[即所有元素都等于根],所以它将是 O(n)。 [无论树的大小如何,都不需要加深超过 1 步]。每个元素 O(1)。

(2) AVL 树的最坏情况:向 AVL 树插入 n 个整数是 O(nlogn)。每一步都是 O(log(T)),其中 T 是当时的大小。 O(log1) + O (log2) + ... + O(logn) = O(log1 + log2 + ... + logn) = O(log(1*...*n)) = O(nlogn)。所以 O(nlogn)。每个元素 O(logn)

(3) 没有强制执行结构,最好的情况,仍然是 O(n),与 (1) 的原因相同。在最好的情况下,你添加的所有元素都是根,所以你永远不需要在树中向下走,不管它的大小是多少。每个元素 O(1)。

(4) 没有强制执行结构,最坏的情况:正如其他答案中所说,找到每个元素的位置是 O(n),所以总的来说,你的时间复杂度最差O(n^2)。每个元素 O(n)。

【讨论】:

    【解决方案2】:

    这在你的定义中是不正确的:

    将 n 个整数插入一棵最初为空的 AVL 树(最佳情况)O(log n)

    您不能在少于 n 的操作中访问(和复制)n 数据项,因为您应该阅读每个项目(因此,O(n) 是在 n 个元素上移动的最低限度)。

    所以,我的假设是您为单个元素提供正确的 O()(这有点错误,因为可以在特殊输入上实现最佳;您的估计是平均情况,而不是最好的),所以,总共描述的操作我将每个乘以O(n)

    • 将 n 个整数插入最初为空的 AVL 树(最佳 情况)O(n*log n) 更新:这是平均值;特殊输入的最佳时间可能会更短。

    • 将 n 个整数插入最初为空的 AVL 树(最坏情况)O(n*log n)

    • 将 n 个整数插入一个初始为空的二叉搜索树,该二叉搜索树不强制执行结构属性(最佳情况)O(n*log n) 更新:这可能取决于实现和整数序列;所以最好的情况是O(n)(见 cmets)。

    • 将 n 个整数插入最初为空的二叉搜索树中,该二叉搜索树不强制执行结构属性(最坏情况)O(n*n)

    【讨论】:

    • BST:最坏的情况并不比最好的情况好。最坏的情况是 O(n^2)。
    • 谢谢!这说明了很多。所以本质上,由于我为每个数据结构插入整数,那么你需要将 n 乘以每个时间复杂度
    • 最好的情况可能意味着最好的情况,如:“它最终将是一个平衡的树”。当然,您可以创建一个随机二叉搜索树,那么您的最坏情况 O(n log n) 的概率非常高。
    • 请注意,将 [1,1,1,1,1,1,1,1,1,1,.....,1] 插入树中不是 O(nlogn),它是 O(n)。
    • 这是不正确的。如果你不强制执行特殊的树属性,你的二叉树将成为一个排序列表,并且将 n 个排序的元素插入一个空的排序列表有 O(n)
    【解决方案3】:

    插入n 整数如何导致O(logn) 的大O。这没有任何意义。当然读取整数本身至少需要O(n)

    因此,对于不平衡的 BST 示例,最坏的情况是您插入一个排序的数字列表,例如 1,2,3,4。插入 1 需要 0 时间。插入 2 需要 ~1 时间。插入 3 需要 ~2 时间。等等。这相当于1+2+3+...+n = O(n^2)

    同样,在最佳情况下,每个后续插入都需要 log(i) 时间。所以总运行时间为log(1)+log(2)+log(3)+...+log(n)。这评估的结果不是很明显。但如果你懂一点微积分,你会发现这(几乎)是从 1 到 n 的 log n 积分的梯形规则近似。这大约是nlogn - n = O(nlogn)

    我相信您可以对 AVL 树进行类似的分析。

    【讨论】:

      【解决方案4】:

      对不起,他们都错了。

      您使用的是用于单次插入的 Big-O。如果你做了 n 个,你就得花上 n 个。

      所以正确的数字是:

      将n个整数插入:

      • AVL 树(最坏情况):O(log(n) * n)
      • AVL 树(最佳情况):这很难,但我猜它也是 O(log(n) * n)
      • 不强制结构属性的二叉搜索树(最佳情况): O(n) - 1 个项目的最佳案例插入时间实际上是 O(1)
      • 不强制结构属性的二叉搜索树(最坏情况): O(n^2) - 如果你不强制执行结构属性,你可能会得到一个完全不平衡的树,所以在最坏的情况下,你的 n 个元素的树的高度为 n => 你的树会变形为一个列表。

      【讨论】:

      • 第4种情况:但是如果树变形为列表,插入n个整数的总时间可以是O(n)(如果我们在树的顶部添加每个新元素 - 所以它是依赖于实现的)
      • @osgx 是对的 - 但是 O(n) 仍然是最好的情况,第 4 种情况是最坏的情况。
      【解决方案5】:

      是的,你是对的,如果你把所有的东西都乘以 n。您的运行时间是针对一个元素的。

      【讨论】:

      • 没有人(在没有 oracle、jinn 或并行机器的帮助下算作单个操作)移动 n 元素的速度比 O(n) 步骤快。
      • 但我只能将“插入 n 个整数”理解为“处理 n 个整数的总时间”,而不是“将单个整数插入到存储 n 个元素的树中”。
      • 不,单个元素的运行时间并不完全正确。
      • 将 [1,1,1,...,1] 插入二叉搜索树是每个元素 O(1)。
      • 这没有任何意义。您想了解算法的运行时间,而不是创建算法运行良好的最佳情况。你也可以说:“我解决了 N=NP,因为我创建了一个一切正常的场景”。这完全无关紧要。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多