有效地找到数组中的元素行列?

时间:2009-11-04 14:55:44

标签: algorithm sorting statistics performance space-efficiency

如何找到数组中每个元素的等级,在关系的情况下平均有效?例如:

float[] rank(T)(T[] input) {
    // Implementation
}

auto foo = rank([3,6,4,2,2]);  // foo == [3, 5, 4, 1.5, 1.5]

我能想到的唯一方法是分配3个数组:

  1. 输入数组的副本,因为它必须进行排序,我们不拥有它。
  2. 用于跟踪输入数组的排序顺序的数组。
  3. 要返回的一系列排名。
  4. 有没有人知道如何在O(N log N)时间和O(1)辅助空间中执行此操作(意味着我们必须分配的唯一数组是我们要返回的数组),或者至少摆脱它上面三个阵列中的一个?

7 个答案:

答案 0 :(得分:4)

您可以分配要返回的数组(让我们称之为R),将其初始化为0..n-1然后“排序”传入的数组(称为I),但使用比较I [R [k ]]与I [R [j]]相比,而不是正常的R [k]与R [j],然后根据需要交换R数组中的值(而不是像往常一样交换I数组中的值)。 / p>

你可以使用quicksort或heapsort(或bubblesort)来实现这种间接排序,但这会破坏你的复杂性。

您只需要分配一个数组 - 并为索引分配一些堆栈空间。

答案 1 :(得分:2)

好的,所以你将输入数组复制到foo。使用heapsort在O(n log n)时间内就地foo排序。现在,取出输入数组的第一个元素,并使用binary search在O(log n)时间内在foo中找到它的等级,并将等级插入ranks数组并返回它。 / p>

现在,您使用2个数组而不是3个。

答案 2 :(得分:0)

如果你不拥有数组,我认为不可能在O(N log N)和空间O(1)中进行。

如果元素的范围(元素的大小)很小,则使用计数。计算每个元素的数量,然后使用计数数组基于输入数组计算结果数组。

c - is counting result,
C - is cumulative counting
C[i] = c[i] + c[i-1] + c[i-2] + ... + c[0]
result[i] = 1 / c[in[i]] + C[in[i]-1]

答案 3 :(得分:0)

为什么不只是复制和排序数组并从那里开始?有许多可用的就地排序算法,例如heapsort。

答案 4 :(得分:0)

用一些简单的代码总结florin's answer(和相关的注释)可能会有用。

以下是如何在Ruby中执行此操作:

arr = [5,1,0,3,2,4]
ranks = (0..arr.length-1).to_a.sort_by{ |x| arr[x] }
# ranks => [2, 1, 4, 3, 5, 0]

在Python中:

arr = [5,1,0,3,2,4]
ranks = range(len(arr))
ranks.sort(key=lambda x:arr[x])
# ranks => [2, 1, 4, 3, 5, 0]

rank数组告诉你0有2级,1有1级,2有4级等等(当然,那些级别从0开始,不是1级。)

答案 5 :(得分:0)

如何使用二进制搜索树并逐个将元素插入到该BST中。然后可以通过在我们想要找到使用顺序遍历BST的元素节点左侧出现的所有元素上保持一个计数器来确定排名。

答案 6 :(得分:0)

我已经使用它在python中快速而又脏了:

def rank(X):
    B = X[:]
    B.sort()
    return [ float(B.index(x)+1) for x in X]

def rank(X):
    B = X[:]
    B = list(set(B))
    B.sort()
    return [ float(B.index(x)+1) for x in X]

第一个示例适用于您在原始列表中没有重复项的情况。它可以做得更好,但我正在玩一些黑客并且出来了。如果你有重复的话,第二个就可以了。