来自数组大小'k'的每个可能子集的最大元素的总和

时间:2013-02-03 17:14:37

标签: python algorithm subset

我有一个非常大的列表,包含大约10,000个元素,每个元素是一个大到50亿的整数。我想从最大大小为10,000个元素的数组的每个可能的大小'k'(由用户给出)子集中找到最大元素的总和。我想到的唯一解决方案是生成每个子集(使用itertools)并找到其最大元素。但这需要花费大量时间!什么是解决这个问题的pythonic方式?

1 个答案:

答案 0 :(得分:6)

不要使用python,首先使用数学。这是一个组合问题:如果您有 n 数组的数组S n 大),并生成所有可能的大小 k <的子集/ em>,您想要计算子集的最大元素的总和。

假设数字都是不同的(尽管它们也不同),你可以精确计算每个数字出现在一个子集中的频率,并从那里开始,而不必实际构建一个子集。你应该把它带到math.stackexchange.com,他们已经把你整理好了。这是它,但没有很好的数学符号:

按递增顺序对数组进行排序,让S_1为最小(第一个)数字, S_2下一个最小的,依此类推。 (注意:从1开始索引)。

  1. S_n,最大的元素,显然是任何子集的最大元素 它是其中的一部分,并且确实有(n-1 choose k-1)个这样的子集。

  2. 在不包含S_n的子集中,有(n-2 choose k-1) 包含S_{n-1}的子集,其中它是最大的元素。

  3. 继续此操作,直到S_k k-th最小的数字 (从最小的数量开始计算),这将是最大的一个 子集:(k-1 choose k-1) = 1。较小的数字(S_1S_{k-1}) 永远不会是最大的:每组k元素都包含一些内容 大。

  4. 总结以上(n-k+1 terms),你的答案是:

    S_n*(n-1 choose k-1) + S_{n-1}*(n-2 choose k-1) + ... + S_k*(k-1 choose k-1)
    

    将术语从最小写到最大,这只是总和

    Sum(i=k..n) S_i * (i-1 choose k-1)    
    
  5. 如果我们在math.stackexchange上你会得到正确的数学符号,但你明白了。