重新排序一个数组,使其按相同的元素分组

时间:2012-12-24 15:27:37

标签: arrays algorithm sorting grouping

我正在研究处理数组的问题,这可以通过排序轻松解决。但是,我的要求实际上比完全排序更放松:我只需要保证,如果数组中有任何相同的元素,它们将在数组中彼此相邻。

是否有一种重新排序数组的算法,使其符合上述标准,只需进行完整排序就更有效了?

5 个答案:

答案 0 :(得分:6)

如果订单不是问题,您可以尝试任何散列技术。 所有散列技术通常会导致类似项目的分组。 对于数组中的每个项目,只需使用哈希函数,并根据您定义的函数对所有元素进行分组。

答案 1 :(得分:3)

所以答案是否定的。这些信息并没有真正帮助。它可能会让你好一点,但不会在大O.

对于每个建议散列获得线性时间的人,你也可以做同样的排序。此方法称为基数/散列排序。它会破坏你的内存使用量。

当有更多限制时,你甚至可以使用更酷的技巧(即总和,xor等)

但是,对于仅在广义数组上使用比较的算法,通过这种方式减少问题,你不会购买太多东西。

为了给出一个简单的直觉,假设每个元素有1个冗余,那么你的数组是a1,a1,... a,a(n个唯一数字的2n个元素)。

解决方案空间的大小是n! (只要aj-aj配对,你可以根据你的问题陈述中指定的方式置换你想要的那对)。输入空间的大小是(2n)!/(2 ^(n))。

这意味着你的算法需要产生足够的信息来安排((2n)!/ n!)/(2 ^ n)=(n *(n + 1)* ... 2n)/(2 ^ n)元素。每次比较都会给你1位信息。所需的比较迭代次数是log(n)+ log(n + 1)... + log(2n)-n,即big_omega(nlog(n))。这不比排序更好或更差。

这是一种半严格的分类处理方法: http://www.cs.cmu.edu/~avrim/451f11/lectures/lect0913.pdf

我可能会被贿赂以生成当前问题的类似证据。

答案 2 :(得分:1)

如果所有元素都可以分成两组,我们可以用哈希解决这个问题 复杂性为time = O(n)additional space = O(1)

如果所有元素都可以划分为三组,我们可以两次应用上述方法 复杂性为time = O(n) * 2 = O(n)additional space = O(1)

如果所有元素都可以分为四组,我们可以将第一种方法应用三次 复杂性为time = O(n) * 3 = O(n)additional space = O(1)

如果所有元素都可以划分为k个组,我们可以应用第一个方法(k-1)次 复杂性为time = O(n) * (k-1) = O(k*n)additional space = O(k)

此方法优于O(k) < O(log n)时的时间复杂度排序

实际上,当所有元素都可以划分为三个组时,Dutch national flag problem提出了Edsger Dijkstra这个问题。

答案 3 :(得分:0)

您对不同的密钥有任何约束吗?

如果没有,你实际上更需要一个哈希包,而不是任何类型的排序。

由于您没有提供任何编程语言,这里有一个python示例:

from collections import defaultdict

data=[ (1,"a"), (2, "c"), (3, "d"), (2, "b") ]

table = defaultdict(lambda: list())
for key, record in data:
     table[key].append(record)

for key, values in table.iteritems():
    for value in values:
        print key, value

这应该以线性时间运行,因为哈希表查找被认为是O(1)。

如果您的数据大于主内存,那么经典的外部排序方法可能会比严重地击中外部哈希表更快。通常,完整排序可以更快,因为算法已经过优化!基准测试也是如此!

答案 4 :(得分:0)

这个想法类似于上面的Python代码,但在CL:

(defun partition (array &key (test #'eql))
  (loop with table = (make-hash-table :test test)
     for i across array do
       (setf (gethash i table) (1+ (gethash i table 0)))
     finally
       (return
         (loop with result = (make-array (length array))
            with pointer = -1
            for key being the hash-keys of table
            for value being the hash-values of table do
              (loop while (> value 0) do
                   (setf (aref result (incf pointer)) key
                         value (1- value)))
            finally (return result)))))

(partition #(1 2 3 "2" "2" "3" 'a 'b 'b 3 3 1 1 "3" 'a))
;; #(1 1 1 2 3 3 3 "2" "2" "3" 'A 'B 'B "3" 'A)

(partition #(1 2 3 "2" "2" "3" 'a 'b 'b 3 3 1 1 "3" 'a) :test #'equal)
;; #(1 1 1 2 3 3 3 "2" "2" "3" "3" 'A 'A 'B 'B)

它也说明了平等的概念不是给定的。您可以定义您认为相同的内容,并且根据该定义,将它与排序速度进行比较可能有意义也可能没有意义(因为排序意味着可以对序列进行排序)。