Loop through different sets of unique permutations
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Generating permutations looks simple until duplicate values enter the input. At that point, a naive loop produces repeated arrangements, which wastes time and makes downstream logic harder to trust.
Why Duplicate Permutations Appear
If all input values are distinct, a standard permutation routine yields n! arrangements with no repeats. The trouble starts when the input contains repeated values such as [1, 1, 2]. A naive algorithm treats the first 1 and second 1 as different positions even though they produce the same final ordering.
One brute-force fix is to generate every permutation and store the results in a set. That works for tiny inputs, but it does extra work and consumes memory for permutations you never wanted in the first place. A better approach is to avoid creating duplicates during the search.
Backtracking for Unique Permutations
The common pattern is:
- Sort the input so duplicates are adjacent.
- Track which positions are already used.
- Skip a value if it is the same as the previous value and the previous value has not been used in the current branch.
That skip rule prevents the algorithm from choosing equivalent values in interchangeable positions.
Output:
This solution scales much better than generating duplicates first and filtering later.
Looping Through Several Input Sets
Many real problems are not "generate one set of permutations." They are "for each input set, generate the distinct orderings and process them." In that case, keep the permutation logic separate from the outer loop.
Structuring the code this way makes it clear where one dataset ends and the next begins. It also lets you replace the inner processing step with validation, scoring, or persistence logic without rewriting the generator.
When itertools.permutations Is Not Enough
Python’s itertools.permutations is fast and convenient, but it does not remove duplicates for repeated input values. You can wrap it in a set, but then you lose streaming behavior and pay an avoidable cost for larger inputs.
This is acceptable for quick experiments. For production logic or larger search spaces, a duplicate-aware backtracking solution is usually the better design.
Choosing the Right Representation
If you only need to iterate once, yielding lists or tuples is enough. If you need to compare or store permutations, tuples are often a better output type because they are hashable and safe to use as dictionary keys. That choice depends on what the next stage of your program needs.
Another useful technique is to stop early. If you are searching for the first permutation that satisfies a condition, do not materialize the whole result set. Iterate lazily and break when you find a match.
Common Pitfalls
- Generating all permutations and then deduplicating with a
setis easy to write but inefficient for repeated values. - Forgetting to sort the input breaks the duplicate-skip rule because equal values are no longer adjacent.
- Reusing the same list object without copying it causes every saved permutation to end up identical.
- Materializing every permutation in memory can become expensive very quickly.
- Mixing the outer dataset loop with the inner backtracking logic makes the code harder to test and reuse.
Summary
- Duplicate values require more than a plain permutation loop.
- A sorted-input backtracking algorithm can avoid repeated arrangements before they are created.
- Keep dataset iteration separate from permutation generation for cleaner code.
- '
itertools.permutationsis useful, but it does not solve uniqueness on its own.' - Prefer lazy iteration when you do not need the entire result set at once.

