第一个脚本使用双 for 循环将输入列表拆分为所有可能的三组列表。对于每个三元组,它计算三元组中每个列表的总和,然后创建一个名为 diffs 的排序列表,其中包含这些总和的绝对差。它将一个由diffs 和后跟三元组组成的元组保存到一个名为all_splits 的列表中。最后,它对all_splits 进行排序,因为all_splits 中的每个项目都以diffs 开头,所以保存的元组按照它们的diffs 从低到高的顺序进行排序。
def split_list_test(lst):
all_splits = []
for i in range(1, len(lst) - 1):
for j in range(i + 1, len(lst)):
splits = [lst[:i], lst[i:j], lst[j:]]
a, b, c = map(sum, splits)
diffs = sorted((abs(c-a), abs(c-b), abs(b-a)), reverse=True)
all_splits.append((diffs, splits))
all_splits.sort()
return all_splits
test = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for row in split_list_test(test):
print(row)
输出
([60, 40, 20], [[10, 20, 30, 40, 50], [60, 70, 80], [90, 100]])
([60, 40, 20], [[10, 20, 30, 40, 50, 60], [70, 80], [90, 100]])
([140, 110, 30], [[10, 20, 30, 40, 50, 60], [70, 80, 90], [100]])
([140, 120, 20], [[10, 20, 30, 40, 50], [60, 70], [80, 90, 100]])
([160, 90, 70], [[10, 20, 30, 40], [50, 60, 70, 80], [90, 100]])
([170, 90, 80], [[10, 20, 30, 40], [50, 60, 70], [80, 90, 100]])
([180, 110, 70], [[10, 20, 30, 40, 50, 60, 70], [80, 90], [100]])
([200, 110, 90], [[10, 20, 30, 40, 50, 60, 70], [80], [90, 100]])
([200, 140, 60], [[10, 20, 30, 40, 50, 60], [70], [80, 90, 100]])
([200, 150, 50], [[10, 20, 30, 40, 50], [60, 70, 80, 90], [100]])
([210, 160, 50], [[10, 20, 30], [40, 50, 60, 70], [80, 90, 100]])
([240, 130, 110], [[10, 20, 30], [40, 50, 60, 70, 80], [90, 100]])
([240, 220, 20], [[10, 20], [30, 40, 50, 60, 70], [80, 90, 100]])
([240, 230, 10], [[10, 20, 30, 40], [50, 60], [70, 80, 90, 100]])
([250, 250, 0], [[10, 20, 30, 40], [50, 60, 70, 80, 90], [100]])
([260, 260, 0], [[10], [20, 30, 40, 50, 60, 70], [80, 90, 100]])
([270, 260, 10], [[10, 20, 30, 40, 50, 60, 70, 80], [90], [100]])
([280, 190, 90], [[10, 20, 30], [40, 50, 60], [70, 80, 90, 100]])
([280, 190, 90], [[10, 20, 30, 40, 50], [60], [70, 80, 90, 100]])
([300, 160, 140], [[10, 20], [30, 40, 50, 60, 70, 80], [90, 100]])
([310, 160, 150], [[10, 20], [30, 40, 50, 60], [70, 80, 90, 100]])
([330, 190, 140], [[10], [20, 30, 40, 50, 60], [70, 80, 90, 100]])
([330, 290, 40], [[10, 20, 30], [40, 50, 60, 70, 80, 90], [100]])
([340, 180, 160], [[10], [20, 30, 40, 50, 60, 70, 80], [90, 100]])
([340, 310, 30], [[10, 20, 30], [40, 50], [60, 70, 80, 90, 100]])
([350, 300, 50], [[10, 20, 30, 40], [50], [60, 70, 80, 90, 100]])
([370, 280, 90], [[10, 20], [30, 40, 50], [60, 70, 80, 90, 100]])
([390, 260, 130], [[10], [20, 30, 40, 50], [60, 70, 80, 90, 100]])
([390, 320, 70], [[10, 20], [30, 40, 50, 60, 70, 80, 90], [100]])
([410, 390, 20], [[10, 20, 30], [40], [50, 60, 70, 80, 90, 100]])
([420, 380, 40], [[10, 20], [30, 40], [50, 60, 70, 80, 90, 100]])
([430, 340, 90], [[10], [20, 30, 40, 50, 60, 70, 80, 90], [100]])
([440, 360, 80], [[10], [20, 30, 40], [50, 60, 70, 80, 90, 100]])
([460, 460, 0], [[10, 20], [30], [40, 50, 60, 70, 80, 90, 100]])
([480, 440, 40], [[10], [20, 30], [40, 50, 60, 70, 80, 90, 100]])
([510, 500, 10], [[10], [20], [30, 40, 50, 60, 70, 80, 90, 100]])
下一个脚本更紧凑一些,它只返回一个解决方案。它使用不同的规则来决定最小拆分。如果(a, b, c) 是三元组中列表的总和,从最低到最高排序,那么这些总和的绝对差是c-a、c-b 和b-a。差值之和为c-a + c-b + b-a,等于2*(c-a),因此我们可以通过查找最小值为c-a 的拆分来找到最小拆分(使用此规则)。
def keyfunc(seq):
sums = sorted(sum(u) for u in seq)
return sums[2] - sums[0]
def split_list(lst):
gen = ([lst[:i], lst[i:j], lst[j:]]
for i in range(1, len(lst) - 1)
for j in range(i + 1, len(lst)))
return min(gen, key=keyfunc)
test = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
print(split_list(test))
输出
[[10, 20, 30, 40, 50], [60, 70, 80], [90, 100]]
如您所见,对于这个test 列表,此版本提供的解决方案与上面找到的最小解决方案之一相同。