Python保持列表顺序拆分为n个非空桶的所有组合实现方法
问题解决方案
核心原理
这个问题属于有序序列的k路连续拆分问题,核心思路是隔板法:
- 长度为
m的列表共有m-1个元素间隙 - 要拆分为
n个非空连续子列表,只需在m-1个间隙中选出n-1个位置插入隔板即可 - 总共有
C(m-1, n-1)种合法拆分组合,完全匹配你给出的示例场景
Python实现代码
基于标准库的简洁实现(推荐)
直接用itertools.combinations生成隔板位置组合,代码量少且高效:
import itertools def split_list_into_buckets(lst: list, bucket_num: int) -> list: m = len(lst) # 边界校验:桶数非法时直接返回空列表 if bucket_num <= 0 or bucket_num > m: return [] # 生成所有隔板位置组合:在m-1个间隙中选bucket_num-1个位置 split_points_list = itertools.combinations(range(1, m), bucket_num-1) result = [] for split_points in split_points_list: # 补充前后边界方便切片 boundaries = [0] + list(split_points) + [m] buckets = [lst[boundaries[i]: boundaries[i+1]] for i in range(bucket_num)] result.append(buckets) return result # 测试用例 if __name__ == "__main__": lst = [1,2,3,4,5,6,7,8,9,10] n = 3 res = split_list_into_buckets(lst, n) for item in res: print(item)
无依赖递归实现
如果不想依赖标准库,可以用递归回溯的方式生成所有拆分:
def split_list_recursive(lst: list, bucket_num: int) -> list: m = len(lst) if bucket_num == 1: return [[lst]] result = [] # 第一个桶最少1个元素,最多留bucket_num-1个元素给剩下的桶 for first_bucket_len in range(1, m - (bucket_num - 1) + 1): first_bucket = lst[:first_bucket_len] rest_buckets_list = split_list_recursive(lst[first_bucket_len:], bucket_num - 1) for rest_buckets in rest_buckets_list: result.append([first_bucket] + rest_buckets) return result
效果验证
以你给出的n=3测试场景为例,运行代码后输出的结果完全匹配示例:
第一个组合:[[1], [2], [3,4,5,6,7,8,9,10]]
第二个组合:[[1], [2,3], [4,5,6,7,8,9,10]]
...
最后一个组合:[[1,2,3,4,5,6,7,8], [9], [10]]
内容的提问来源于stack exchange,提问作者Poyraz Tahan
相关产品推荐
相关产品推荐

