算法 - 组/排序列表,以最大化最小平均组值

时间:2015-10-25 20:51:59

标签: python algorithm sorting optimization

我正在寻找一些用Python编写算法的帮助来完成以下任务:

  

给定一个实数列表,将列表排序/分组为n个较小的列表,以使平均最小组值最大化。

例如,考虑将下面的列表分组为两个列表 - A和B,每个列表包含两个元素。

lis = [1,1,2,2]

在下面的第一个场景中,每个列表的最小值为1,因此平均最小值为1.

# Scenario 1
A = [1,2]
B = [1,2]

# Scenario 2
A = [1,1]
B = [2,2]

在第二种情况下,A的最小值为1,B的最小值为2,因此平均最小值为1.5。这种安排是最佳的。

很明显,对类似的值进行分组会更好。我可以用Jenks natural breaks optimization(或一维k均值聚类)来做到这一点。但是,我不确定我的目标和Jenks优化的目标是否(数学上)等效。

任何帮助或意见都将不胜感激。

编辑:较小的列表必须具有相同的大小(假设给定的列表总是分成没有余数的较小的组)。

2 个答案:

答案 0 :(得分:2)

似乎最简单的方法是对列表进行初始排序,以便始终将最低值组合在一起,例如:

# Define the list of values to group
values = [1, 2, 3, 10, 11, 12]

# Sort the values
values.sort()

# Split the values down into an even number of `n` groups
no_groups = 3
group_size = len(values) / no_groups
groups = []

for i in range(0, no_groups):
    groups.append(values[0:(group_size)])
    values = values[group_size:]

# Calculate the average minimum value of the groups
average_min = float(sum([g[0] for g in groups])) / no_groups

print(average_min)

但鉴于你提到Jenks和K-means聚类,我担心这太简单了,我错过了什么?

答案 1 :(得分:1)

解决此问题的最佳方法是将数字从最小值排序到最大值,然后将排序后的列表拆分为n组,而无需进一步重新排列。任何改进此分组的尝试都会降低其中一个组的最小值,从而降低最小值的平均值。

一个例子可能有助于解释原因。

给出一个包含12个数字的列表:

[94, 82, 61, 2, 96, 34, 87, 13, 82, 91, 61, 39]

排序列表是:

[2, 13, 34, 39, 61, 61, 82, 82, 87, 91, 94, 96]

如果我们想要n=3组,那么这些组就是:

[[2, 13, 34, 39], [61, 61, 82, 82], [87, 91, 94, 96]]

因此,最小值的平均值为avg(2,61,87)=50

你能做得比这更好吗?答案是否定的。

将任何数字从一个组A移动到另一个组B将减少A的最小值,而不会相应地增加B的最小值。

例如,你可能会认为将61移动到另一个组会有所帮助。

一种可能的重新安排是:

[[2, 13, 34, 61], [39, 61, 82, 82], [87, 91, 94, 96]]

此重新排列的值为avg(2,39,87)=42

另一种可能的重新安排是:

[[2, 13, 34, 39], [87, 61, 82, 82], [61, 91, 94, 96]]

此重新排列的值为avg(2,61,61)=41

所以你看,我们不能通过移动61来做得更好。同样,我们也不能通过移动任何数字来做得更好。