How to obtain all subsequence combinations of a String in Java, or C etc
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A subsequence is any sequence you get by keeping characters in their original order and optionally skipping some of them. For a string of length n, there are 2^n subsequences, so the main challenge is not the algorithm itself but understanding the growth rate and generating them cleanly.
The Core Idea
For each character, you have exactly two choices:
- include it in the current subsequence
- exclude it from the current subsequence
That binary choice naturally leads to recursion or to a bitmask-based loop. Both approaches generate the same result set.
For the string "abc", the subsequences are:
- '
""' - '
"a"' - '
"b"' - '
"c"' - '
"ab"' - '
"ac"' - '
"bc"' - '
"abc"'
The empty string is a valid subsequence unless your problem statement explicitly says to omit it.
Java Recursive Solution
A recursive backtracking solution is usually the clearest way to express the problem.
This works by exploring the “skip” branch first and the “take” branch second. The exact output order can vary depending on the branch order, but the set of subsequences is the same.
Bitmask Alternative
If you prefer an iterative solution, use the binary representation of numbers from 0 to 2^n - 1. Each bit says whether the character at that position should be included.
This version is compact and easy to reason about if you are comfortable with bit operations.
C++ Version
The same recursive idea translates directly to C++.
If you need the result in sorted order, sort the output afterward. Subsequence generation itself does not imply lexicographic order.
Repeated Characters Change The Situation
If the input contains duplicate letters, such as "aab", the naive algorithm still explores 2^n positions, but some generated subsequences will be identical. Whether that is correct depends on the problem.
- If the task is to enumerate subsequences by index choice, duplicates are expected.
- If the task is to list unique subsequence strings, store results in a
Setor deduplicate after generation.
Do not silently change this behavior unless you know which interpretation the problem expects.
Complexity Matters
Time complexity is O(n * 2^n) if you account for constructing output strings. Space usage also grows quickly if you store every result.
That means generating all subsequences is practical only for small strings. At length 20, you already have over one million subsequences. Sometimes the correct solution is not to materialize them all, but to process each subsequence on the fly.
Common Pitfalls
The biggest pitfall is confusing subsequences with substrings. Substrings must stay contiguous. Subsequences only preserve relative order.
Another common mistake is forgetting the empty subsequence. Many textbook definitions include it, so verify the requirement before dropping it.
People also underestimate duplicate handling when the string contains repeated characters. A correct index-based generator can still produce repeated strings.
Finally, do not ignore the exponential growth. The algorithm is simple, but the output size dominates quickly.
Summary
- Every character creates two choices: include or exclude.
- Recursive backtracking is the clearest general solution.
- A bitmask loop is a clean iterative alternative.
- Duplicate input characters can create duplicate subsequence strings.
- Generating all subsequences is inherently exponential, so use it only for small inputs.

