如何用高效Pythonic方式解决组合元组最大最小差求和的内存问题
高效计算n元素组合的最大最小差之和
直接生成所有组合的方式完全不可行——你的列表有50个元素,选40个的组合数是C(50,40)=10272278170,这个量级的组合既存不下也遍历不完。我们可以用数学方法绕开生成组合的步骤,直接计算结果:
核心思路是:所有组合的max-min之和 = 所有组合的max值总和 - 所有组合的min值总和。我们只需要分别算出每个元素在多少个组合里充当max或min,再用元素值乘以次数求和即可。
具体推导
先对列表升序排序,设排序后的列表为sorted_lst,总元素数为m:
计算元素作为max的次数:
对于sorted_lst[i](第i个元素,0-based),要让它成为组合的最大值,组合里的所有元素必须来自它及它前面的元素(共i+1个),且不能全是它前面的元素(否则最大值会是更小的元素)。因此次数为:C(i+1, n) - C(i, n)
(其中C(a,b)是组合数,当a < b时结果为0,代表该元素不可能成为任何n元素组合的max)计算元素作为min的次数:
对于sorted_lst[i],要让它成为组合的最小值,组合里的所有元素必须来自它及它后面的元素(共m-i个),且不能全是它后面的元素(否则最小值会是更大的元素)。因此次数为:C(m-i, n) - C(m-i-1, n)
(同样,当可用元素数不足n时,组合数为0)
实现代码
import math def comb(a, b): # 处理组合数无效的情况:a < b 或 b < 0时返回0 return math.comb(a, b) if a >= b >= 0 else 0 lst = [639, 744, 947, 856, 102, 639, 916, 665, 766, 679, 679, 484, 658, 559, 564, 3, 384, 763, 236, 404, 566, 347, 866, 285, 107, 577, 989, 715, 84, 280, 153, 76, 24, 453, 284, 126, 92, 200, 792, 858, 231, 823, 695, 889, 382, 611, 244, 119, 726, 480] n = 40 sorted_lst = sorted(lst) m = len(sorted_lst) # 计算所有组合的max值总和 sum_max = sum( num * (comb(i + 1, n) - comb(i, n)) for i, num in enumerate(sorted_lst) ) # 计算所有组合的min值总和 sum_min = sum( num * (comb(m - i, n) - comb(m - i - 1, n)) for i, num in enumerate(sorted_lst) ) result = sum_max - sum_min print(result)
为什么高效
- 时间复杂度:排序是O(m log m),两次遍历求和是O(m),整体复杂度极低;
- 内存复杂度:只需要存储排序后的列表和几个中间变量,完全不会出现内存溢出的问题;
- 组合数计算用Python内置的
math.comb,高效且支持大整数运算,能轻松处理C(50,10)这种量级的数值。
内容的提问来源于stack exchange,提问作者Wasim Aftab
相关产品推荐
相关产品推荐

