我试图了解如何从壁纸对算法的n log ^ 2 n时间到n log n时间。我得到以下部分(来自http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPairDQ.html)
步骤4是一种需要O(n log n)时间的排序,它占据所有其他步骤,这是需要减少到O(n)的时间,以便整个算法实现O(n log) n)时间。这是我很难理解的部分。作者提出
步骤1:将集合划分为...,并递归计算每个部分的距离,按y坐标按排序顺序返回每个集合中的点。 第4步:在O(n)时间内将两个已排序的列表合并为一个已排序的列表。
您仍然需要在递归步骤中按y坐标对点进行排序,这需要O(n log n)时间。我们怎能避免这种情况?合并是O(n),但我们仍然必须在某处进行排序。
答案 0 :(得分:1)
O( n log n )出现问题的原因是我们一遍又一遍地这样做:如果我们将集合划分为两个子集,并将其中的每一个划分为两个子集,然后涉及七种类型(整个集合中有一个,两个上半部分,四个四分之一)。
所以提案通过重用以前的排序结果来解决这个问题:所以我们对最小的分区进行完全合并排序(每个分区都是O(1),总计为O( n )) ,但是对于较大的分区,我们只需要执行单个O( n )合并传递来组合这些结果。所以我们只需要支付O( n log n )价格一次,这很好。
答案 1 :(得分:0)
他们的建议是你有两个(已经排序的列表)A和B.可以使用merge sort将这些组合成一个排序列表(恰好是步骤(4)中的合并步骤中的合并步骤) 。
合并排序的结果是一个排序列表,包含A和B的所有成员。一旦合并,就不需要再对任何内容进行排序。
答案 2 :(得分:0)
我提供了一种可能更容易理解的替代解决方案。首先在y坐标上对所有点进行排序。这是一次使用O(n log n)。有n个点,并且在排序的数组中,每个点都有一些最多为n的索引。保存每个点的索引(为索引添加整数到点数据结构)。然后运行原始算法。这一次,在我们想要对点进行排序的那一刻,不要使用正常的比较排序对它们进行排序。但是根据他们的索引对它们进行排序我们可以根据它们的索引用O(n)中的基数排序对它们进行排序。所以总过程是O(n log n),因为我们只使用了比较排序一次,其余的是T(n)= 2T(n / 2)+ O(n)。但是常数不如问题中提出的修改那么好。
问题中建议的修改过程就像合并排序中的合并一样:当我们有两个排序列表时,我们不需要使用正常排序再次对它们进行排序,我们可以通过在O(n)中合并它们来对它们进行排序。