Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 分区比排序容易吗?_Algorithm_Sorting_Partitioning_Time Complexity - Fatal编程技术网

Algorithm 分区比排序容易吗?

Algorithm 分区比排序容易吗?,algorithm,sorting,partitioning,time-complexity,Algorithm,Sorting,Partitioning,Time Complexity,这是一个一直萦绕在我脑海中一段时间的问题 假设我有一个项目列表和它们的等价关系,比较两个项目需要固定的时间。 我想返回项目的一个分区,例如一个链表列表,每个链表包含所有等价的项目 一种方法是将等价性扩展到对项目的排序,并对其进行排序(使用排序算法);然后,所有同等项目将相邻 但这能比排序更有效吗?这个问题的时间复杂度是否低于排序问题?如果不是,为什么不呢?基于比较的排序通常有一个下限O(n logn) 假设您迭代您的项目集,并将它们放入具有相同比较值的项目的存储桶中,例如在一组列表中(例如使用哈

这是一个一直萦绕在我脑海中一段时间的问题

假设我有一个项目列表和它们的等价关系,比较两个项目需要固定的时间。 我想返回项目的一个分区,例如一个链表列表,每个链表包含所有等价的项目

一种方法是将等价性扩展到对项目的排序,并对其进行排序(使用排序算法);然后,所有同等项目将相邻


但这能比排序更有效吗?这个问题的时间复杂度是否低于排序问题?如果不是,为什么不呢?

基于比较的排序通常有一个下限O(n logn)

假设您迭代您的项目集,并将它们放入具有相同比较值的项目的存储桶中,例如在一组列表中(例如使用哈希集)。此操作显然是O(n),即使在从集合中检索列表列表之后也是如此

---编辑:---

这当然需要两个假设:

  • 每个要分区的元素都有一个固定时间哈希算法
  • 桶的数量不取决于输入量

因此,分区的下限是O(n)。

如果必须使用比较器,则下限是Ω(n logn)比较,用于排序或分区。原因是必须检查所有元素Ω(n),比较器必须对每个元素执行对数n比较,以唯一地识别或放置该元素相对于其他元素(每个比较将空间划分为2,因此对于大小为n的空间,需要对数n比较)


如果每个元素都可以与一个在恒定时间内导出的唯一键相关联,则下限为Ω(n),用于排序蚂蚁分区(c.f.)

如果您可以为项目定义哈希函数以及等价关系,然后,您应该能够在线性时间内进行分区——假设计算散列是常数时间。哈希函数必须将等效项映射到相同的哈希值

如果没有散列函数,则必须将要插入分区列表的每个新项与每个现有列表的标题进行比较。该策略的效率取决于最终将有多少分区

假设您有100个项目,它们最终将被划分为3个列表。然后,在将每个项目插入其中一个列表之前,必须将其与最多3个其他项目进行比较


然而,如果这100个项目最终会被划分成90个列表(也就是说,很少有同等的项目),情况就不同了。现在,您的运行时更接近于二次而非线性。

如果您不关心等价集的最终顺序,那么划分为等价集可能会更快。然而,这取决于算法和每个集合中元素的数量

如果每个集合中只有很少的项,那么您最好对元素进行排序,然后找到相邻的相等元素。对于n个元素,一个好的排序算法是O(n logn)

如果有几个集合中有很多元素,那么可以获取每个元素,并与现有集合进行比较。如果它属于其中一个,则添加它,否则创建一个新集合。这将是O(n*m),其中n是元素的数量,m是等价集的数量,对于大n和小m,这小于O(n logn),但随着m趋于n,情况会更糟


组合排序/分区算法可能更快。

通常,分区比排序更快,因为您不必将每个元素与每个潜在的等效已排序元素进行比较,只需将其与已建立的分区键进行比较。仔细看一看。基数排序的第一步是根据密钥的某些部分对输入进行分区。基数排序为O(kN)。如果数据集的键以给定的长度k为界,则可以对其进行基数排序O(n)。如果您的数据是可比较的,并且没有一个有界键,但是您选择了一个有界键来对集合进行分区,那么对集合进行排序的复杂性将是O(n log n),而分区的复杂性将是O(n)。

您似乎一次问了两个不同的问题

1) 若只允许相等性检查,那个么分区是否比排序更容易?答案是否定的。您需要进行ω(n^2)比较,以确定最坏情况下的分区(例如,所有情况都不同)

2) 如果允许排序,分区比排序容易吗?答案再次是否定的。这是因为。也就是说,为了确定所有对象是否都是不同的,需要进行欧米茄(nlogn)比较。由于排序可以在O(nlogn)时间内完成(也有欧米茄(nlogn)下界)并解决划分问题,因此渐近地它们同样困难

如果选择任意散列函数,则相等的对象不必具有相同的散列,在这种情况下,您没有通过将它们放入散列表来完成任何有用的工作

即使您提出了这样一个散列(保证具有相同散列的相等对象),对于好的散列,时间复杂度预计为O(n),最坏的情况是ω(n^2)

是否使用哈希或排序完全取决于问题中不可用的其他约束


其他答案似乎也忘记了您的问题(主要)是关于比较分区和排序的

使用哈希函数执行可能不完美的分区所需的时间将是O(n+bucketcount)[而不是O(n*bucketcount)]。使bucket count足够大以避免所有冲突将是昂贵的,但是如果hash函数工作得很好,那么每个bucket中应该有少量不同的值。如果可以轻松生成多个统计上独立的散列函数,则可以获取每个