求将任意长度无重复物品列表放入N个单物品容量箱子的所有最大填充排列方案的简便实现方法
求将任意长度无重复物品列表放入N个单物品容量箱子的所有最大填充排列方案的简便实现方法
嘿,这个问题其实不用纠结递归啦!咱们可以用组合+排列的思路,借助现成的工具函数轻松实现,比自己写递归逻辑简单太多了,而且代码可读性还强。
先明确你要的「最大填充」核心需求:
- 如果物品数量 ≤ 箱子数N:把所有物品都用上,剩下的箱子留空,要生成所有不同的放置顺序
- 如果物品数量 > 箱子数N:选N个物品填满所有箱子,要生成所有可能的物品组合+每个组合的全排列
核心逻辑拆解
当物品数M ≤ N时:
本质是从N个箱子位置里选M个位置,把M个物品按不同顺序放进去,剩下的位置补占位符。这对应数学里的「排列数P(N, M)」,也就是N个位置选M个的有序排列。当物品数M > N时:
先从M个物品里选出所有N个物品的组合(组合数C(M, N)),然后对每个组合生成全排列(每个组合有N!种排列方式),所有组合的排列加起来就是所有填满箱子的方案。
Python 实现示例
咱们用Python的itertools模块(标准库自带,不用额外安装)来实现,代码简洁又靠谱:
import itertools def get_max_fill_arrangements(items, n_bins, placeholder="_"): item_count = len(items) arrangements = [] if item_count <= n_bins: # 第一步:选M个箱子位置的组合 for positions in itertools.combinations(range(n_bins), item_count): # 第二步:对物品生成所有全排列,填充到选中的位置 for item_perm in itertools.permutations(items): bin_arr = [placeholder] * n_bins for pos, item in zip(positions, item_perm): bin_arr[pos] = item arrangements.append(bin_arr) else: # 第一步:选N个物品的所有组合 for item_combo in itertools.combinations(items, n_bins): # 第二步:对每个组合生成全排列,直接作为填满的箱子方案 arrangements.extend(list(itertools.permutations(item_combo))) # 统一把元组转成列表(permutations返回元组,保持输出格式一致) arrangements = [list(arr) if isinstance(arr, tuple) else arr for arr in arrangements] return arrangements
验证你的例子
测试第一个例子:
items = ["A", "B"], n_bins=3
调用函数后得到的结果和你给出的完全一致,一共6种排列:[["A","B","_"], ["B","A","_"], ["A","_","B"], ["_","A","B"], ["B","_","A"], ["_","B","A"]]测试第二个例子:
items = ["A","B","C","D"], n_bins=3
会生成4组(对应4种3物品组合),每组6种排列,总共24种,和你的示例完全匹配。
为什么这个方法比递归简单?
不用自己处理递归的边界条件、栈溢出风险,直接借助标准库的成熟工具函数,代码行数少、逻辑清晰,别人看代码也能快速理解你的意图,维护起来也方便。
备注:内容来源于stack exchange,提问作者CWRules
相关产品推荐
相关产品推荐

