多数值近似均等分配的优化方案及多列表分配方法咨询
多数值近似均等分配的优化方案及多列表分配方法咨询
嘿,我来帮你拆解这个问题~首先针对你现有的分配方法,我们可以优化得更均衡;另外关于多列表的分配逻辑,也有清晰的思路可以参考。
一、更均衡的两列表分配方案
你当前的思路是先降序排序,再把元素往总和更小的列表里加,直到列表满了再转向另一个。这个贪心策略简单高效,但有时候会因为列表长度的限制,错过更优的分配组合——毕竟当其中一个列表先满5个元素后,剩下的元素只能全丢去另一个,可能拉大和的差距。
针对10个元素分成两个各5个的场景,我们可以试试改进的贪心策略,或者在数据量小的情况下直接用回溯法找最优解:
1. 改进版贪心(更均衡的贪心逻辑)
排序后,我们先保证两个列表的元素数量同步增长,再根据总和调整分配方向,比“先填满一个”的方式更容易得到均衡结果:
import random # 生成随机数列表 intList = [random.randint(10, 200) for _ in range(10)] intList.sort(reverse=True) listX = [] listY = [] for num in intList: # 优先填补元素更少的列表;元素数相同则往总和更小的列表加 if len(listX) < len(listY): listX.append(num) elif len(listY) < len(listX): listY.append(num) else: if sum(listX) <= sum(listY): listX.append(num) else: listY.append(num) print(f"listX = {listX} \nlistY = {listY}\nsumX = {sum(listX)}, sumY = {sum(listY)}")
2. 回溯法找最优解(绝对均衡)
如果追求理论上最均衡的分配(总和差最小),因为元素数量只有10个,回溯法的计算量完全可以接受,它会遍历所有可能的5+5分配组合,找到总和差最小的那一组:
import random intList = [random.randint(10, 200) for _ in range(10)] intList.sort(reverse=True) min_diff = float('inf') best_x = [] best_y = [] def backtrack(index, current_x, current_y): global min_diff, best_x, best_y # 终止条件:所有元素分配完毕 if index == len(intList): if len(current_x) == 5 and len(current_y) ==5: diff = abs(sum(current_x) - sum(current_y)) if diff < min_diff: min_diff = diff best_x = current_x.copy() best_y = current_y.copy() return # 尝试把当前元素加入x(如果x还没满) if len(current_x) <5: current_x.append(intList[index]) backtrack(index+1, current_x, current_y) current_x.pop() # 尝试把当前元素加入y(如果y还没满) if len(current_y) <5: current_y.append(intList[index]) backtrack(index+1, current_x, current_y) current_y.pop() backtrack(0, [], []) print(f"最优分配:\nlistX = {best_x} \nlistY = {best_y}\nsumX = {sum(best_x)}, sumY = {sum(best_y)}\n差值:{min_diff}")
二、多列表的分配方法
如果是要把数据分配到多个目标列表(每个最多5个元素),核心思路是扩展贪心策略:每次把当前最大的元素加到当前总和最小且未填满的列表里,循环直到所有元素分配完毕。
举个分配到3个列表的实现例子:
import random intList = [random.randint(10, 200) for _ in range(12)] # 12个元素,分配到3个列表(最多各5个) intList.sort(reverse=True) # 初始化3个空列表 target_lists = [[], [], []] for num in intList: # 筛选出未满的列表,按总和排序后取最小的那个添加元素 available = [lst for lst in target_lists if len(lst) <5] available.sort(key=lambda x: sum(x)) available[0].append(num) # 打印结果 for i, lst in enumerate(target_lists, 1): print(f"list{i} = {lst},总和:{sum(lst)}")
如果是从多个源列表取数分配,可以先把所有源列表的元素合并成一个大列表,再按上面的多列表分配逻辑处理;如果需要保留源列表的归属,可以给每个元素带上来源标记,分配后再按需拆分。
备注:内容来源于stack exchange,提问作者권대현
相关产品推荐
相关产品推荐

