如何高效地找到数组中每个元素的排名,当有并列时取平均值?例如:
float[] rank(T)(T[] input) {
// Implementation
}
auto foo = rank([3,6,4,2,2]); // foo == [3, 5, 4, 1.5, 1.5]
我唯一能想到的方法需要分配3个数组:
- 输入数组的一个副本,因为它必须排序且我们不拥有它。
- 用于跟踪输入数组排序顺序的数组。
- 要返回的等级数组。
如何高效地找到数组中每个元素的排名,当有并列时取平均值?例如:
float[] rank(T)(T[] input) {
// Implementation
}
auto foo = rank([3,6,4,2,2]); // foo == [3, 5, 4, 1.5, 1.5]
如果你不拥有该数组,我认为不可能以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]
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]
排名数组告诉你0的排名为2,1的排名为1,2的排名为4等等。(当然,这些排名从零开始,而不是从一开始。)
我在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]
第一个例子适用于您的原始列表中没有重复项的情况。它可以做得更好,但我正在尝试一些技巧并得出了这个结果。如果您有重复项,则第二个例子将起作用。