将K长度列表分成尽可能"均匀"的L个子列表,即使K/L有余数

1 投票
3 回答
619 浏览
提问于 2025-04-16 22:25

我不知道怎么更好地表达我想要的,所以请耐心听我说。

假设我有一个包含17个元素的列表。为了简单起见,我们用 ABCDEFGHIJKLMNOPQ 来表示这个列表。如果我想把它分成7个“足够均匀”的子列表,可能会像这样:

ABC DE FGH IJ KL MNO PQ

在这里,每个子列表的长度分别是 3, 2, 3, 2, 2, 3, 2。最长的子列表比最短的子列表多一个元素:ABC DE FGH I JKL MN OPQ 也有七个子列表,但这里的长度差距是两个。

此外,看看每对3之间有多少个2:这遵循同样的规则,即长度差距 ≤ 1。在 ABC DEF GH IJ KLM NO PQ 中,长度差距也是1,但它们不均衡:3, 3, 2, 2, 3, 2, 2。理想情况下,如果继续以这种方式减少子列表,数字之间的差距永远不会超过1。

当然,有不止一种方法可以“均匀”地将列表分成子列表。我并不想要一个详尽的解决方案集——如果我能得到一个Python的解决方案,适用于任何长度的列表和任何数量的子列表,那对我来说就足够了。问题是我甚至不知道从哪里开始解决这个问题。有没有人知道我在找什么?

3 个回答

0

可以查看“grouper”的例子,地址是 http://docs.python.org/library/itertools.html

3

这段内容来自StackOverflow,主要讨论了一个编程问题。虽然我不能直接回答问题,但我可以帮你理解其中的内容。

在编程中,很多时候我们会遇到一些错误或者问题,这些问题可能是因为代码写得不够清晰,或者是因为我们对某些概念理解得不够透彻。解决这些问题的关键在于仔细阅读错误信息,并尝试找出代码中可能出错的地方。

同时,向社区寻求帮助也是一个很好的选择。像StackOverflow这样的平台上,有很多经验丰富的程序员,他们愿意分享自己的知识和经验,帮助新手解决问题。

记住,编程是一个不断学习和实践的过程,遇到问题是很正常的,重要的是要保持耐心,逐步解决它们。

>>> s='ABCDEFGHIJKLMNOPQ'
>>> parts=7
>>> [s[i*len(s)//parts:(i+1)*len(s)//parts] for i in range(parts)]
['AB', 'CD', 'EFG', 'HI', 'JKL', 'MN', 'OPQ']


>>> import string
>>> for j in range(26):
...  print [string.uppercase[i*j//parts:(i+1)*j//parts] for i in range(parts)]
... 
['', '', '', '', '', '', '']
['', '', '', '', '', '', 'A']
['', '', '', 'A', '', '', 'B']
['', '', 'A', '', 'B', '', 'C']
['', 'A', '', 'B', '', 'C', 'D']
['', 'A', 'B', '', 'C', 'D', 'E']
['', 'A', 'B', 'C', 'D', 'E', 'F']
['A', 'B', 'C', 'D', 'E', 'F', 'G']
['A', 'B', 'C', 'D', 'E', 'F', 'GH']
['A', 'B', 'C', 'DE', 'F', 'G', 'HI']
['A', 'B', 'CD', 'E', 'FG', 'H', 'IJ']
['A', 'BC', 'D', 'EF', 'G', 'HI', 'JK']
['A', 'BC', 'DE', 'F', 'GH', 'IJ', 'KL']
['A', 'BC', 'DE', 'FG', 'HI', 'JK', 'LM']
['AB', 'CD', 'EF', 'GH', 'IJ', 'KL', 'MN']
['AB', 'CD', 'EF', 'GH', 'IJ', 'KL', 'MNO']
['AB', 'CD', 'EF', 'GHI', 'JK', 'LM', 'NOP']
['AB', 'CD', 'EFG', 'HI', 'JKL', 'MN', 'OPQ']
['AB', 'CDE', 'FG', 'HIJ', 'KL', 'MNO', 'PQR']
['AB', 'CDE', 'FGH', 'IJ', 'KLM', 'NOP', 'QRS']
['AB', 'CDE', 'FGH', 'IJK', 'LMN', 'OPQ', 'RST']
['ABC', 'DEF', 'GHI', 'JKL', 'MNO', 'PQR', 'STU']
['ABC', 'DEF', 'GHI', 'JKL', 'MNO', 'PQR', 'STUV']
['ABC', 'DEF', 'GHI', 'JKLM', 'NOP', 'QRS', 'TUVW']
['ABC', 'DEF', 'GHIJ', 'KLM', 'NOPQ', 'RST', 'UVWX']
['ABC', 'DEFG', 'HIJ', 'KLMN', 'OPQ', 'RSTU', 'VWXY']
1

如果你有一个长度为 N 的列表,想要分成 S 个子列表,那么可以从带余数的除法开始。比如说,当 N 等于 17,S 等于 7 时,你可以计算出 17 除以 7 等于 2,余数是 3。这意味着你可以先准备 7 个长度为 2 的子列表,但要记得还有 3 个子列表需要加长 1。因为你总共有 7 个子列表,而需要增加长度的有 3 个,所以你可以计算 X = 7 除以 3,然后用这个值作为步长:先增加第一个子列表的长度,然后是第 X 个子列表,再然后是第 2X 个子列表,依此类推。

如果这个方法不适合你,我建议你找一本书,叫做 The Algorithm Design Manual,作者是 Skiena,里面有很多关于集合和树的算法。

http://www.algorist.com/

撰写回答