【问题标题】:Finding time and space complexity寻找时间和空间复杂度
【发布时间】:2015-11-17 00:43:39
【问题描述】:

我一直在学习排序。 大多数排序算法(合并、快速等)都使用数组。

我在想,如果我不对数组进行适当的排序会怎样。

我想到的一个算法是

  • 遍历数组中的每个元素 - O(n)。
  • 对于每个元素,将该元素与双向链表的开始和结束元素进行比较。
  • 将元素添加到链表中的正确位置。 (根据哪个更快,从列表的开头/结尾开始迭代)。
  • 当原始数组中的所有元素都排序后,创建后台线程将它们复制到数组中。在未完成复制之前,通过迭代列表返回索引元素。
  • 复制完成后,通过数组索引返回元素。

现在,它的时间复杂度是多少?如何计算?

【问题讨论】:

  • 成本 O(N^2),空间 O(N)(如果原始数据已经在列表中,则 O(1))。请参阅 C 中的列表插入排序代码en.wikipedia.org/w/…

标签: algorithm sorting time-complexity


【解决方案1】:

让我们一步一步来。

遍历数组中的每个元素 - O(n)。

是的!

对于每个元素,将该元素与双向链表的开始和结束元素进行比较。

将元素添加到链表中的正确位置。 (根据哪个更快,从列表的开始/结束开始迭代)。

假设双向链表当前有 k 个元素。不幸的是,仅通过查看列表的前后元素,您将无法判断该元素可能在列表中的哪个位置。您的元素很可能在值上更接近列表的前面元素而不是后面,但实际上应该属于后面元素之前。您也无法在链表中进行随机访问,因此在最坏的情况下,您可能必须扫描链表的所有 k 个元素,试图找到该元素所属的位置。这意味着完成的工作在最坏的情况下将是 O(k)。现在,算法的每次迭代都会将 k(列表中元素的数量)增加一,所以在最坏的情况下所做的工作是 1 + 2 + 3 + ... + n = Θ(n2)。

当原始数组中的所有元素都排序后,创建后台线程将它们复制到数组中。在未完成复制之前,通过迭代列表返回索引元素。

复制完成后,通过数组索引返回元素。

这是一个有趣的想法,它的复杂性很难衡量。如果后台线程被饿死或真的很慢,那么在最坏的情况下查找任何元素的成本将是 O(n),因为您可能必须扫描列表中一半以上的元素才能找到您要查找的元素正在寻找。

总的来说,您的算法运行时间为 O(n2) 并使用 Θ(n) 内存。它本质上是插入排序的一种变体(正如@Yu Hao 所指出的那样),在实践中,我希望这比仅使用标准的 O(n log n) 排序算法甚至就地排序算法要慢得多插入排序,由于链表提供的额外内存开销和较差的引用局部性。

【讨论】:

  • 谢谢。很好的解释。
【解决方案2】:

你描述的算法基本上是Insertion sort的变体版本。

这里使用链表的主要原因是避免数组中元素的额外交换。将元素与双向链表的头部和尾部进行比较可以提供较小的性能改进(如果有的话)。

随机输入的时间复杂度仍然是O(N2)。

【讨论】:

  • 答案的重要部分是我如何计算它。我学习了递归方法和大师方法。但不知道如何实现它们。
猜你喜欢
  • 1970-01-01
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
  • 2013-09-12
  • 2016-02-13
  • 1970-01-01
相关资源
最近更新 更多