我正在寻找一个需要2个输入的算法(#1:数字,#2:数字数组[可能重复]):
输出应该是所需的组(其中包含原始列表中的各个数字)。这些组的长度/大小应该尽可能接近。请注意,如果一个数字在一个组中,则列表中具有相同编号的所有其他项目将放在同一个组中。 (例如,你不会在多个输出组中输入数字3)。
请注意,返回组中的元素不得在其数字范围内重叠
所以你不能有这样的[[1,1,1,2,2,4,4,4],[3,3,5,5,6,7,8,16]]两个输出组,因为每个子组中的数字范围是[1-4]和[3-16],它们具有重叠。您只能拥有[1-3] [4-16]之类的组(注意在这种情况下没有重叠)。
示例#1输入/输出
1) 3 Desired Groups
2) List: [1,1,2,2,3,3]
输出:
[[1,1],[2,2],[3,3]]
示例#2输入/输出
输入2个要输出的所需组/子阵列,以及以下数字列表:
[1,1,1,2,2,3,3,4,4,4,5,5,6,7,8,16]
输出是两个包含以下内容的子数组:
[1,1,1,2,2,3,3,4,4,4]
[5,5,6,7,8,16]
注1:输出[[1,1,1,2,2,3] [4,4,4,5,5,6,7,8,16]]的两个子阵列/组因为无法输出相同的组,所以也是有效的。
注意#2:虽然子组:[[1,1,1,2,2,4,4,4],[3,3,5,5,6,7,8,16]]将是它的长度相等,它违反了规则"返回的子组之间没有重叠的范围",这意味着每个子组中的数字范围不能相互重叠。 (例如,在这个注释中,返回的子组的范围是[1-4]和[3-16],如果你拿一个标尺并从数字1-4中画出一条线并从3-16中画另一条线,你会看到3-4会有重叠的线条,这不是我们想要的情况)。
在此示例的示例输出中,两组的范围是[1-4]和[5-16],如果您使用标尺/卷尺并绘制了数字所在的行,则这些行将为彼此不重叠,这就是我们想要的。
示例#3输入/输出
输入3个要输出的所需组/子阵列,以及以下数字列表:
[1,1,1,2,2,3,3,4,4,4,5,5,6,7,8,16]
输出:
[1,1,1,2,2]
[3,3,4,4,4]
[5,5,6,7,8,16]
请注意,在这种情况下,由于没有办法实现相同的项目数,算法输出的效果最好,只有一个组只比其他组大1个。
示例#4输入/输出 输入:" 4个所需的组",以及以下列表: [1,1,1,2,3,3,4,4,4,5,5,6,7,8,16]
可能的输出:
[1,1,1,2,2]
[3,3,4,4,4]
[5,5,6]
[7,8,16]
注意:优选地,输出应尽可能包含多于1个唯一编号。虽然[[1,1,1],[2,2,3,3],[4,4,4,5,5],[6,7,8,16]]的输出确实提供了大致相似的分组,优选在单个子组中存在多于1个唯一编号。在这个" Note"中,1是组1中唯一的数字,而在本例的示例输出中,组1包含唯一的数字1和2,这是首选。
执行此操作的好方法是什么?
答案 0 :(得分:0)
您可以使用.map()
和.filter()
创建包含相同元素的数组数组,收集数组的值,其中单个数组存在于单个数组中,如果存在,{{1}从收集的数组中预期的数组(组)数量,将原始单个值重新插入到组中,返回结果
.splice()
答案 1 :(得分:0)
我的上一个解决方案没有给出正确的结果,所以这是一个不同的algorithm
。它如下:
如果您遵循该算法,您可以看到它将由branching
关闭不同的合并列表,直到它达到该分支结束所需的长度之一。这是写recursive function
的绝佳机会。
但在此之前,我们需要一种小方法来对原始列表中的公共数字进行分组。为此,小for-loop
遍历每个数字并检查它是否属于先前常用数字的一部分。如果是,请将其添加到它们,否则它会创建自己的公共数字。
这看起来像是:
l = [1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6]
l.sort()
groups = []
for i in l:
if groups and i in groups[-1]:
groups[-1].append(i)
else:
groups.append([i])
现在groups
是:
[[1], [2, 2], [3, 3, 3], [4, 4], [5, 5], [6]]
所以我们已准备好recursive funtion
:
def merge(grps, numGrps):
global solutions
if len(grps) <= numGrps:
solutions.append(grps)
return
merges = [grps[:i] + [grps[i] + grps[i+1]] + grps[i+2:] for i in range(len(grps)-1)]
for m in merges:
merge(m, numGrps)
该函数不言自明,但list-comprehension
是控制分支的重要部分:
[grps[:i] + [grps[i] + grps[i+1]] + grps[i+2:] for i in range(len(grps)-1)]
实质上是这样说:对于当前列表的length
之前的每个数字,请在它之前取公共号码组grps[:i]
,将它们添加到与其合并的公共号码grps[i]
上下一个常用数字grps[i+1]
然后将其添加到其余常用数字grps[i+2:]
。
从那里开始,我们只需将function
设置为每个不同的合并公共号combinations
及其目标组数。
最终的代码放在一起:
l = [1,2,2,3,3,3,4,4,5,5,6]
l.sort()
groups = []
for i in l:
if groups and i in groups[-1]:
groups[-1].append(i)
else:
groups.append([i])
print("original list:")
print(l, "\n")
print("common numbers grouping:")
print(groups)
print()
def merge(grps, numGrps):
global solutions
if len(grps) <= numGrps:
solutions.append(grps)
return
merges = [grps[:i] + [grps[i] + grps[i+1]] + grps[i+2:] for i in range(len(grps)-1)]
for m in merges:
merge(m, numGrps)
solutions = []
merge(groups, 3)
print("possible solutions:\n")
for s in solutions:
print(s)
输出:
original list:
[1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6]
common numbers grouping:
[[1], [2, 2], [3, 3, 3], [4, 4], [5, 5], [6]]
possible solutions:
[[1, 2, 2, 3, 3, 3, 4, 4], [5, 5], [6]]
[[1, 2, 2, 3, 3, 3], [4, 4, 5, 5], [6]]
[[1, 2, 2, 3, 3, 3], [4, 4], [5, 5, 6]]
[[1, 2, 2, 3, 3, 3, 4, 4], [5, 5], [6]]
[[1, 2, 2], [3, 3, 3, 4, 4, 5, 5], [6]]
[[1, 2, 2], [3, 3, 3, 4, 4], [5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4, 5, 5], [6]]
[[1, 2, 2], [3, 3, 3, 4, 4, 5, 5], [6]]
[[1, 2, 2], [3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4], [5, 5, 6]]
[[1, 2, 2], [3, 3, 3, 4, 4], [5, 5, 6]]
[[1, 2, 2], [3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3, 4, 4], [5, 5], [6]]
[[1, 2, 2, 3, 3, 3], [4, 4, 5, 5], [6]]
[[1, 2, 2, 3, 3, 3], [4, 4], [5, 5, 6]]
[[1, 2, 2, 3, 3, 3, 4, 4], [5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4], [5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4], [5, 5, 6]]
[[1], [2, 2, 3, 3, 3, 4, 4], [5, 5, 6]]
[[1], [2, 2, 3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3, 4, 4], [5, 5], [6]]
[[1, 2, 2], [3, 3, 3, 4, 4, 5, 5], [6]]
[[1, 2, 2], [3, 3, 3, 4, 4], [5, 5, 6]]
[[1, 2, 2, 3, 3, 3, 4, 4], [5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4], [5, 5, 6]]
[[1, 2, 2], [3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2], [3, 3, 3, 4, 4, 5, 5, 6]]
[[1, 2, 2], [3, 3, 3, 4, 4], [5, 5, 6]]
[[1], [2, 2, 3, 3, 3, 4, 4], [5, 5, 6]]
[[1], [2, 2], [3, 3, 3, 4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4, 5, 5], [6]]
[[1, 2, 2], [3, 3, 3, 4, 4, 5, 5], [6]]
[[1, 2, 2], [3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2], [3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2, 3, 3, 3, 4, 4, 5, 5], [6]]
[[1], [2, 2], [3, 3, 3, 4, 4, 5, 5, 6]]
[[1, 2, 2], [3, 3, 3], [4, 4, 5, 5, 6]]
[[1], [2, 2, 3, 3, 3], [4, 4, 5, 5, 6]]
[[1], [2, 2], [3, 3, 3, 4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4], [5, 5, 6]]
[[1, 2, 2], [3, 3, 3, 4, 4], [5, 5, 6]]
[[1, 2, 2], [3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2, 3, 3, 3], [4, 4], [5, 5, 6]]
[[1], [2, 2, 3, 3, 3, 4, 4], [5, 5, 6]]
[[1], [2, 2, 3, 3, 3], [4, 4, 5, 5, 6]]
[[1, 2, 2], [3, 3, 3, 4, 4], [5, 5, 6]]
[[1], [2, 2, 3, 3, 3, 4, 4], [5, 5, 6]]
[[1], [2, 2], [3, 3, 3, 4, 4, 5, 5, 6]]
[[1, 2, 2], [3, 3, 3], [4, 4, 5, 5, 6]]
[[1], [2, 2, 3, 3, 3], [4, 4, 5, 5, 6]]
[[1], [2, 2], [3, 3, 3, 4, 4, 5, 5, 6]]
现在您已经全部了可能的解决方案,您可以按照任何方式对其进行排序。因此,例如,如果您想在组中选择长度最均匀的那个,您将计算每个组的长度,smallest
和biggest
长度之间的差异将是其中的分数你排名他们。
即使有其他方法对它们进行排序,正如我们在评论部分看到的那样,上面描述的那个似乎是大多数人想要的,所以这里是:
smallestDiff = 9999
for s in solutions:
lenDiff = max([len(a) - len(b) for a in s for b in s])
if lenDiff < smallestDiff:
smallestDiff = lenDiff
sol = s
以及我的列表示例:
[1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6]
我们得到了结果:
[[1, 2, 2], [3, 3, 3, 4, 4], [5, 5, 6]]
在这种情况下,我认为这是最好的解决方案。最后,要查看问题中给出的示例:
groups = 3
l = [1, 1, 2, 2, 3, 3]
输出:
[[1, 1], [2, 2], [3, 3]]
groups = 2
l = [1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 7, 8, 16]
输出:
[[1, 1, 1, 2, 2, 3, 3], [4, 4, 4, 5, 5, 6, 7, 8, 16]]
很明显这个算法有效,我希望这会有所帮助。
答案 2 :(得分:-1)
我们可以使用itertools.groupby
将重复的项目组合在一起,然后使用简单的"greedy" algorithm将每个组分配到子列表。如果我们在主循环的末尾有任何剩余的项目,我们将它们放在一个新的子列表中,除非我们已经达到了所需的子列表数量,在这种情况下我们只是将剩余的东西添加到最后一个现有的子列表中。
结果并不完美:取决于数据,它甚至可能无法创建足够的子列表,但是对于表现良好的数据,结果是合理的,恕我直言。 ;)
from itertools import groupby
def equal_groups(seq, num):
grouplen = len(seq) // num
result, current = [], []
for _, g in groupby(seq):
g = list(g)
# If this group is too big to go in current, flush current
if current and len(current) + len(g) > grouplen:
result.append(current)
current = []
current.extend(g)
# Deal with any leftovers
if current:
if len(result) < num:
result.append(current)
else:
result[-1].extend(current)
return result
# Test
data = [1,1,1,2,2,3,3,4,4,4,5,5,6,7,8,16]
for i in range(1, 8):
print(i, equal_groups(data, i))
<强>输出强>
1 [[1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 7, 8, 16]]
2 [[1, 1, 1, 2, 2, 3, 3], [4, 4, 4, 5, 5, 6, 7, 8, 16]]
3 [[1, 1, 1, 2, 2], [3, 3, 4, 4, 4], [5, 5, 6, 7, 8, 16]]
4 [[1, 1, 1], [2, 2, 3, 3], [4, 4, 4], [5, 5, 6, 7, 8, 16]]
5 [[1, 1, 1], [2, 2], [3, 3], [4, 4, 4], [5, 5, 6, 7, 8, 16]]
6 [[1, 1, 1], [2, 2], [3, 3], [4, 4, 4], [5, 5], [6, 7, 8, 16]]
7 [[1, 1, 1], [2, 2], [3, 3], [4, 4, 4], [5, 5], [6, 7], [8, 16]]