How do I generate all permutations of a list?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Generating all permutations of a list means enumerating every possible ordering of its elements. In Python, the practical default is itertools.permutations, because it is correct, concise, and lazy. The harder part is usually not the syntax. It is recognizing that the number of permutations grows factorially, so generating all of them can become infeasible very quickly.
Use itertools.permutations First
For most real code, the standard library already provides the correct tool.
This yields tuples such as (1, 2, 3) and (3, 2, 1). If you need lists instead of tuples, convert them explicitly.
That covers the majority of use cases cleanly.
Understand the Growth Before You Materialize
A list of length n has n! permutations.
- '
3!is6' - '
5!is120' - '
8!is40320' - '
10!is3628800'
That is why the best implementation is often the lazy one. If you only need to scan permutations until one matches a condition, do not convert the iterator to a list. Iterate and stop early.
This can save a large amount of memory and time.
Write a Backtracking Version Only When You Need Control
If you need custom pruning, learning value, or nonstandard behavior, a backtracking implementation is useful.
This works by choosing which element should occupy each position, recursing, and then undoing the choice before trying the next branch.
That algorithm is useful when the standard iterator is not enough, but it should not be the first thing you write for an everyday permutation task.
Handle Duplicates Deliberately
If the input contains repeated values, naive generation will produce repeated permutations.
If you only need unique permutations, one simple solution is to deduplicate afterward.
That is fine for small inputs. For larger inputs with many duplicates, a custom algorithm that skips repeated choices is more efficient than generating duplicates and removing them later.
Partial Permutations Are Often Enough
Many problems do not actually need full-length permutations. itertools.permutations can generate ordered selections of length r.
This is useful when the task is “all ordered pairs” or “all ordered triples,” not “all full rearrangements of the whole list.”
Recognizing that difference can turn an expensive problem into a manageable one.
Think About the Goal, Not Just the Tool
Permutation generation often appears inside optimization or search tasks. In those cases, the deeper question is whether you really need every ordering. Sometimes a greedy algorithm, dynamic programming approach, or constraint-based search is the better model.
It is worth asking that question early because permutations become expensive very fast. Generating them all is correct, but not always wise.
Common Pitfalls
- Converting the entire permutation iterator to a list when lazy iteration would have been enough.
- Forgetting that the number of permutations grows as
n!and becomes infeasible quickly. - Reimplementing the algorithm when
itertools.permutationsalready solves the practical problem. - Ignoring duplicate input values and then being surprised by repeated outputs.
- Generating full permutations when the actual problem only needs ordered selections of smaller length.
Summary
- In Python,
itertools.permutationsis the standard and usually best solution. - Permutations grow factorially, so feasibility matters as much as syntax.
- Keep the result lazy unless you truly need all permutations materialized.
- Use backtracking only when you need custom control beyond the standard library.
- Handle duplicates and partial-length cases deliberately based on the real problem.

