Smallest Subsequence of Distinct Characters - Problem

Imagine you have a string of characters and you need to pick the lexicographically smallest subsequence that contains every distinct character exactly once. This is like creating the most optimal representative sample from your string!

Given a string s, your task is to return the lexicographically smallest subsequence of s that contains all the distinct characters of s exactly once.

What makes this challenging?

  • You must maintain the relative order of characters from the original string (subsequence property)
  • You want the lexicographically smallest result possible
  • Each distinct character must appear exactly once

Example: For string "cbacdcbc", the answer is "acdb" because it's the smallest possible subsequence containing all distinct characters {a, b, c, d} exactly once.

Input & Output

example_1.py โ€” Basic Case
$ Input: s = "bcabc"
โ€บ Output: "abc"
๐Ÿ’ก Note: The distinct characters are 'a', 'b', and 'c'. The lexicographically smallest subsequence containing all of them exactly once is "abc".
example_2.py โ€” Complex Case
$ Input: s = "cbacdcbc"
โ€บ Output: "acdb"
๐Ÿ’ก Note: The distinct characters are 'a', 'b', 'c', and 'd'. We need to find the lexicographically smallest subsequence. Starting with 'a', then 'c' (since we need it), then 'd', then 'b' gives us "acdb".
example_3.py โ€” Single Character
$ Input: s = "aaa"
โ€บ Output: "a"
๐Ÿ’ก Note: Only one distinct character 'a', so the result is "a".

Constraints

  • 1 โ‰ค s.length โ‰ค 104
  • s consists of lowercase English letters
  • Important: The result must be a subsequence (maintain relative order) and contain each distinct character exactly once

Visualization

Tap to expand
Monotonic Stack Algorithm VisualizationProcessing: "cbacdcbc" โ†’ Target: lexicographically smallest subsequenceCharacter Counts: c=4, b=2, a=1, d=1Processing 'c': Add to empty stackcStack: [c]Processing 'b': b < c and c appears later โ†’ remove c, add bcbStack: [b]Processing 'a': a < b and b appears later โ†’ remove b, add abaStack: [a]Processing 'c': a < c, so keep a and add cacStack: [a,c]Processing 'd': c < d, so add dacdStack: [a,c,d]Processing remaining: Skip used chars, need bWhen we see 'b' again: d > b but count[d]=0 โ†’ can't remove dacdbFinal: "acdb"๐ŸŽฏ Key Insight: We can only remove a character from the stack if:1. The new character is lexicographically smaller, AND2. The character to remove still has remaining occurrences (count > 0)
Understanding the Visualization
1
Count Resources
Count how many times each character appears - this tells us if we can afford to skip a character now
2
Greedy Selection
For each character, decide whether to include it now or wait for a better position
3
Smart Backtracking
If we find a better character, remove recent worse choices (but only if they can be added back later)
4
Optimal Result
The stack contains our optimal selection maintaining both lexicographic order and the subsequence property
Key Takeaway
๐ŸŽฏ Key Insight: The monotonic stack allows us to make locally optimal decisions while maintaining the ability to backtrack when we discover globally better choices, as long as we haven't exhausted our future opportunities for the characters we remove.
Asked in
Google 45 Amazon 38 Meta 32 Microsoft 25
52.0K Views
High Frequency
~18 min Avg. Time
1.3K Likes
Ln 1, Col 1
Smart Actions
๐Ÿ’ก Explanation
AI Ready
๐Ÿ’ก Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen