Generating All Combinations of List n Levels Deep in Java
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Problems described as "all combinations of a list n levels deep" usually mean one of two things: combinations from a single list, or the Cartesian product across multiple levels of choices. In Java, the most common recursive solution for the multi-level case is backtracking: build one partial result, recurse to the next level, and remove the last choice when you return.
Clarify the Problem Shape First
Suppose you have a list of lists like this:
- level 1:
A, B - level 2:
1, 2 - level 3:
X, Y
The desired output is often:
- '
A, 1, X' - '
A, 1, Y' - '
A, 2, X' - '
A, 2, Y' - '
B, 1, X' - '
B, 1, Y' - '
B, 2, X' - '
B, 2, Y'
That is not the same as choosing unordered subsets from one flat list. It is a depth-by-depth product of choices.
Recursive Backtracking Fits Naturally
Backtracking works well because the structure is recursive by definition:
- choose one item at the current depth
- recurse to the next depth
- when you return, remove that item and try the next choice
A Java implementation looks like this:
This produces every valid path through the levels.
Why Backtracking Works
The algorithm explores a tree of choices. At each depth, it tries every value available at that level. The current list holds the partial path so far.
The important detail is this line:
You must copy the current path before storing it. Otherwise, later backtracking steps would mutate the same list object and corrupt every saved result.
Iterative Alternatives
You can also build the product iteratively. Start with one empty combination, then expand it level by level.
Conceptually:
- start with
[[]] - for each new level, append each option to each existing partial combination
- replace the partial list with the newly expanded one
This can be elegant for some workloads, but the recursive version is often easier to understand and adapt.
Complexity
If each level has m choices and there are n levels, the total number of outputs is roughly m^n. That means the algorithm must do exponential work because the output itself is exponential.
This is an important point: no clever implementation can avoid that if you truly need every combination. The best you can do is generate them efficiently and avoid unnecessary overhead.
If You Really Meant Simple Combinations
Sometimes the phrase "combinations" refers to choosing k items from one list rather than building one choice per level. That is a different problem and needs a different backtracking rule.
So before optimizing, make sure everyone agrees on whether the target is:
- Cartesian product across levels
- or
k-element combinations from one collection
Many implementation errors come from solving the wrong combinatorics problem.
Common Pitfalls
The biggest mistake is forgetting to copy the current path before adding it to the results. That causes every stored result to end up identical.
Another mistake is mixing up Cartesian products and unordered combinations. They sound similar in English but are not the same algorithm.
People also underestimate output size. If each level has many choices, the number of results grows very quickly.
Finally, watch for empty levels. If one level has no choices, the full product is empty, and your method should handle that case deliberately.
Summary
- Multi-level "combinations" in Java are often really a Cartesian product problem.
- Recursive backtracking is a clean way to generate every path through the levels.
- Copy the current partial result before storing it.
- The output size is inherently exponential in the number of levels.
- Make sure the problem is not actually asking for simple
k-element combinations instead.
Related reading
- Generating all factors of a number given its prime factorization
- Generating all permutations excluding cyclic rotations
- Generating all permutations of a given string
- Generating all permutations of a given string
- Generating ids for a set of integers
- Generating strongly-connected, uniformly-distributed, random di-graphs
- Generating permutations lazily
- Generating permutations of a set most efficiently

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.