我正在尝试解决以下任务: 我给出了n个元素的数组。众所周知,并非所有数组的键都是不同的,但是给出的是我们有k个不同的元素(当然k <= n)。 赋值是在O(n log(log n))最坏情况下对数组进行稳定排序,而k = O(log n)。我允许使用O(n)额外内存。
我目前的解决方案如下所述:
使用大小为k的链接创建一个哈希表,执行以下操作: 如果哈希函数试图将元素插入到已经有值的地方 - 它会检查它们是否相等 - 如果它们是将它添加到列表中,如果不是它开始在数组中移动直到它找到一个地方具有相同的值或空的空间(永远是第一个)。
这样,每个地方的列表只包含具有相同键的元素。哈希表的插入是从原始数组的开始到结束,因此每个列表都是稳定排序的。 然后使用mergeSort对哈希表中的数组进行排序(对于列表,我们将第一个元素视为一个并移动它)。
完成合并排序后,我们按顺序将元素复制回原始数组,每当我们遇到一个列表时,我们按顺序复制每个元素。
以下是我不确定的事项:
是否可以这么说因为哈希表的大小为k而我们只有k个不同的元素,统一哈希承诺哈希函数试图给出不同值的数据在数组中的相同位置可以忽略不计,因此,它的构建时间复杂度是O(n)?
因为如果是这样,算法的运行时似乎是O(n + k log k)= O(n + log n * log(log n))。 这肯定比O(n log k)要好。
答案 0 :(得分:2)
我认为您使用哈希表进入正确的轨道,但我认为您不应该在哈希表中插入元素,然后再将它们复制出来。您应该仅使用哈希表来计算每个不同值的元素数。
接下来,通过按顺序遍历所有值并将前一个元素的计数添加到其起始索引来计算每个不同值的起始索引:
i
的起始索引=元素i-1
的起始索引+元素i-1
的计数。此步骤需要对哈希表中的k
元素进行排序,这些元素相当于O(k log k)= O(log n log log n)运算,远小于步骤1的O(n)和3.
最后,再次遍历输入数组,在表中查找,并在输出数组中找到它的位置。您复制元素,并增加其值的元素的起始索引,以便在它之后复制下一个元素。
如果项目的比较值是连续整数(或某些小范围内的整数),则可以使用数组而不是哈希表进行计数。
这称为counting sort。
答案 1 :(得分:2)
与此处的注释相同:
您创建一个二叉树,任何树: 每个节点都是一个具有不同键的元素列表。
现在我们迭代数组,并在树中搜索每个键, 搜索将采用log(log(n)),因为树中最多有log(n)个不同的节点。 (如果键不存在,我们只需将其作为树的节点添加)。
所以迭代数组将需要O(n * log(log(n))),因为我们给出了n个元素。
最后,由于这是二叉搜索树,我们可以按顺序调用, 并获得数组的排序顺序。
,剩下的就是将它们组合成单个数组。 这将花费O(n)时间。
所以我们得到O(n + n log(log(n))= O(n log(log(n)))