itertools.permutations最省事但返回迭代器,需转list查看;大数据应for循环逐个处理;不自动去重;回溯法可控制去重、剪枝,有两种实现方式。

itertools.permutations 生成全排列最省事,但别直接 print
它返回的是迭代器,不是列表,直接 print(permutations([1,2,3])) 只会看到类似 <itertools.permutations object at></itertools.permutations> 的东西,啥也看不到。
- 要立刻看结果,得转成 list:
list(permutations([1,2,3])) - 如果数据大(比如长度 >10),别无脑转 list,内存会爆;该用 for 循环逐个处理:
for p in permutations(items): process(p) - 它对重复元素不自动去重,
permutations([1,1,2])会返回 6 个结果,其中含重复排列(因为内部按位置区分)
回溯法手写全排列,关键在“交换 + 恢复”或“路径 + used 数组”
想控制去重、剪枝、或理解原理,就得自己写。两种主流写法,区别在状态管理方式:
- 用索引交换(原地修改):每次把
i到末尾的每个元素换到当前位置,递归后必须swap回来,否则后续分支错乱 - 用
path和used数组(更直观):每次选一个未用过的元素追加到path,递归完从path弹出,used[i]设回False - 去重前提:输入先排序,然后跳过
nums[i] == nums[i-1] and not used[i-1]这种情况(保证相同元素按顺序填入)
性能差一倍?别在循环里反复调用 list(permutations(...))
每次调用 permutations 都新建迭代器,但真正耗时的是后续遍历。常见低效写法:
- 错误:在 for 循环里反复写
for p in list(permutations(arr)): ...—— 每次都重新生成全部排列再转 list - 正确:只生成一次,存变量:
perms = list(permutations(arr)),再遍历perms - 回溯法若没剪枝,时间复杂度固定是 O(n!),和
itertools一样;但它的常数更大(函数调用、列表拷贝等),小数据看不出,n=10 以上就明显慢
字符串、元组、自定义对象也能排,但注意不可变类型限制
permutations 不关心内容类型,只按序列长度和索引操作。但实际用时容易卡住:
立即学习“Python免费学习笔记(深入)”;
- 传字符串:
permutations('abc')返回的是('a','b','c')这样的元组,拼成字符串得''.join(p) - 传元组或 namedtuple:没问题,但结果仍是元组,不能直接修改
- 传 list 嵌套 list:会按外层 list 的元素排列,不会 flatten;想排内层元素得先
flatten或单独处理 - 回溯法里如果传 mutable 对象(如 list)进递归并原地改,记得深拷贝
path.copy()再 append,否则所有结果指向同一份内存
itertools 就不够用了,回溯的结构弹性才体现出来。










