【问题标题】:Big-O of an operation over a single linked list对单个链表的操作的 Big-O
【发布时间】:2011-01-23 19:38:20
【问题描述】:

假设你有一个大小为 N 的链表,并且你想对每个元素执行一个操作,从末尾开始。

我想出了以下伪代码:

while N > 0
    Current = LinkedList 
    for 0 to N
        Current = Current.tail
    end
    Operation(Current.head)
    N := N-1
end

现在我必须确定这个算法是哪个 Big-O。
假设 Operation() 是 O(1),我认为它是这样的:

N + (N-1) + (N-2) + ... + (N-(N-1)) + 1

但我不确定 Big-O 到底是什么。我认为它肯定比 O(N^2) 小,但我认为你也不能说它的 O(N) ...

【问题讨论】:

  • 1+2+3+...+n = n*(n+1)/2 这是 O(n^2)
  • 我不太了解你的结构,你有一个名为 Current 的 LinkedList(它看起来像一个节点),它有尾部和头部?如果您打算上一个/下一个,那么它是双重链接的;如果它们确实是头/尾,那么上面的代码根本没有意义。
  • @bestsss:嗯,你可以说 LinkedList 是一个对象,每次我进入 While-Loop 时,我都会在 Current 中引用它。在 Current(即 LinkedList)上调用“head”,返回实际的 Element,“tail”返回另一个 LinkedList 对象,包含,嗯,tail...
  • 好吧 :) 好吧,你有奇怪的想法如何命名“下一个”/“元素”。头/尾通常在节点(本身)之外用于链接列表的指定节点。无论哪种方式,您都有嵌套循环,几乎自动意味着 n2。如果您需要反向处理单个链表,请先对其进行逆向处理,然后再对其进行逆向处理。比你现在拥有的要快得多。逆是O(n),过程是O(n),再逆是O(n)。

标签: linked-list big-o pseudocode


【解决方案1】:

您的方程式基本上是triangular numbers 的方程式,总和为N(N+1)/2。我会让你从中确定O()

一种更快的方法是构造一个与原始列表相反的新列表,然后对其执行操作。

【讨论】:

  • 好吧,不需要构造新列表 [O(n) 内存 - 用于节点/数组]。 inverse/process/inverse 也是可行的。
  • @bestsss:如何在 O(n) 时间内就地反转单链表?
  • 使用相同的节点,这是一个经典问题;例如这个:stackoverflow.com/questions/4686011/invert-linear-linked-list/… -- 也没有额外的内存,即 O(n) 时间,O(1) 内存
【解决方案2】:

您的算法是 O(n^2),正如您在帖子中所建议的那样。不过,您可以在 O(n) 内完成。

请务必记住,Big-O 表示法是算法时间复杂度的上限

【讨论】:

    【解决方案3】:

    1+2+3+...+n = n*(n+1)/2 = 0.5*n^2+O(n)

    这是 O(n^2),并且 O(n^2) 很紧,即没有更低的运行时顺序包含您的运行时。

    从前到后工作的更快算法可能需要 O(n) 而不是 O(n^2)

    【讨论】:

    • 从后到前工作的算法也可以是 O(n)。请参阅@Oli 的回答。
    • @Carl 你是对的,但这需要 O(n) 额外的内存,或者喜欢列表的临时突变。两者都不好。
    • 这绝对是真的,但不好和不可能是完全不同的事情。
    【解决方案4】:

    您的运行时间分析是正确的,运行时间是 1 + 2 + ... + N,即 sum of the arithmetic progression,因此 = (N²-N) / 2。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-01
      • 2015-08-22
      • 2012-04-19
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      相关资源
      最近更新 更多