计算所有排序数组组合的平均值

Calculate average value of all sorted array combinations

我需要得到 n choose k 绘图在排序数组中的统计期望值。

举个例子,假设我想从下面的排序数组中选择 2 个元素

[1, 2, 3]

所有可能组合的集合如下:

(1, 2)
(1, 3)
(2, 3)

所以第一个元素的期望值为(1 + 1 + 2) / 3 = 1.33,第二个元素的期望值为(2 + 3 + 3) = 2.67

这是一个使用暴力破解方法的函数,但在大型数组上使用它太慢了。 有smarter/faster方法吗?

import itertools
import math
def combinations_expected_value(arr, k):
    sums = [0] * k
    l = math.comb(len(arr), k)
    for comb in itertools.combinations(arr, k):
        for i in range(k):
            sums[i] += comb[i]
    
    return [sums[i] / l for i in range(k)]

谢谢!

对于组合中的每个位置,可能的值是从该位置开始到最后一个 k-p-1 元素的列表子集。例如对于 1..100 中 6 的组合,位置 3 只能包含值 3..96

对于 positon/value 对中的每一对,出现次数将是左侧元素组合与右侧元素组合的乘积。

例如,对于 1..100 列表中的 6 个元素的组合,45 出现在第三个位置的次数是 2 in 1..44 的组合乘以 3 in 46 的组合..100。所以我们将有 C(44,2) * C(55,3) * 45 positon/value 对。

您可以对每个 positon/value 对重复此计算,以获得输出组合中每个位置的总数。然后将这些总数除以组合数得到 expected value:

from math import comb

def countComb(N,k):
    result = [0]*k
    for p in range(k):                 # p is count on the left
        q = k-p-1                      # q is count on the right
        for i in range(p,len(N)-q):
            left  = comb(i,p)          # combinations on the left >= 1
            right = comb(len(N)-i-1,q) # combinations on the right >= 1
            result[p] += left * right * N[i]
    return result
            
def combProb(N,k):
    Cnk = comb(len(N),k)
    return [S/Cnk for S in countComb(N,k)]

输出:

print(countComb([1,2,3],2)) # [4, 8]
print(combProb([1,2,3],2))  # [1.3333333333333333, 2.6666666666666665]

print(countComb([1,2,3,4,5],3)) # [15, 30, 45]
print(combProb([1,2,3,4,5],3))  # [1.5, 3.0, 4.5]

# test with large number of combinations:

print(countComb(list(range(1,301)),7))
[1521500803497675, 3043001606995350, 4564502410493025, 
 6086003213990700, 7607504017488375, 9129004820986050,
 10650505624483725]

print(combProb(list(range(1,301)),7))
[37.625, 75.25, 112.875, 150.5, 188.125, 225.75, 263.375]