多个列表中元素的最小组合,以使所有元素至少出现一次

时间:2019-03-08 04:10:47

标签: python algorithm combinations

所以我的问题是这样:

有多个组,每个组包含多个人以及一个等级。 例如

GroupA = [('Joe', 1), ('Kate', 2), ('Jeff', 1)]
GroupB = [('Sam', 1), ('Jim', 2), ('Stephanie', 2)]
GroupCC = [('Adam', 2), ('David', 1), ('Liz', 1), ('Michael', 2)]
  • 我正在组建多个团队,每个团队中只有一个人,因此每个团队都只有3个人。 例如['Kate', 'Sam', 'Adam']

  • 一个人可以属于多个团队,但等级1的人应该具有优先权。如果有多个等级为1的人员,则应平均分配。

我可以组建最少的团队人数,以便每个球员都属于一个团队吗?

在这种情况下,显而易见的答案是4个团队,因为listC具有最多的元素。这也意味着将有一个来自listA和list B的人被包含两次。我想确保两次使用的人是列表A中的Joe或Jeff,以及列表B中的Sam。

1 个答案:

答案 0 :(得分:1)

首先,让我们将其推广到任意数量的组

GroupA = [('Joe', 1), ('Kate', 2), ('Jeff', 1)]
GroupB = [('Sam', 1), ('Jim', 2), ('Stephanie', 2)]
GroupC = [('Adam', 2), ('David', 1), ('Liz', 1), ('Michael', 2)]
groups = [GroupA, GroupB, GroupC]

然后,我们将遍历各个组,并根据需要重复元素(优先级为1)。我们还将从列表中的每个元素中去除排名。

max_len = max(map(len, groups))

names = []
for group in groups:
    subgroup = list(group)
    if any(rank == 1 for _, rank in group):
        subgroup = list(filter(lambda x:x[1] == 1, group))
    group += subgroup * (max_len - len(group))
    names.append([name for name, _ in group])

现在的名称包含名称列表,名称重复至少需要多次以匹配最长的组(可能更多,zip将对其进行裁剪)。

我们将这些列表压缩在一起,并获得我们的团队。

teams = list(zip(*names))

结果:

>>> print("\n".join(map(str, teams)))
('Joe', 'Sam', 'Adam')
('Kate', 'Jim', 'David')
('Jeff', 'Stephanie', 'Liz')
('Joe', 'Sam', 'Michael')