Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
Keep a 'seen' set; for each character, if it isn't in the set, append it and add it. O(n) time, O(k) space.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you combine a seen-set with an order-preserving build.
Where candidates slip
Reordering output, or O(n²) concatenation.
How to stand out
Use the `set.add` boolean idiom to filter and record in one step.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 1 · Optimal
Seen set build
1Hint 1Explore hintHide hint
What structure tells you 'have I already kept this char?'
2Hint 2Explore hintHide hint
Append only on first sighting to preserve order.
3Hint 3Explore hintHide hint
Use a StringBuilder; `set.add` returns true only when newly added.
A · Core idea
Keep only the first occurrence of each character: track a seen set and append a character to the output only the first time you encounter it. Combines the seen-set membership pattern with a filtered build.
Why a set preserves order. You scan left to right and append on first sighting, so the kept characters appear in their original order — no sorting. Later repeats fail the membership test and are skipped.
The Java idiom `seen.add(ch)`. Set.add returns true only when the element was newly added, so if (seen.add(ch)) sb.append(ch); both records and filters in one line.
Performance. Use a StringBuilder, not +=, to keep the build O(n). The set gives O(1) membership, so the whole thing is O(n) time, O(k) space.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
s = "banana"b
new
b"ban"C · Code with teaching comments
D · Why it works and complexityO(n) timeO(k) spaceOpen the invariant and proofExplore the proofHide the proof
ComplexityO(n) time, O(k) space — O(1) set lookup and append per character; the set holds k ≤ alphabet-size keys.
E · Edge cases and pitfalls5s = "aabbcc" — → "abc".Explore edge casesHide edge cases
Edge cases handled
s = "aabbcc"→ "abc".s = "abc"Already unique → "abc".s = ""Empty → "".
Pitfalls
- Not preserving original order (e.g. sorting).
- Using String += in the loop.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic String removeDuplicates(String s) { StringBuilder sb = new StringBuilder(); java.util.Set<Character> seen = new java.util.HashSet<>(); for (char ch : s.toCharArray()) { if (seen.add(ch)) sb.append(ch);Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
- Not preserving original order (e.g., sorting).
- Using String += in the loop.
Revise
Carry the pattern into the interview
Pattern to remember
Seen-set filtered build
Code pattern to memorize
seen=set(); for ch: if ch not in seen: seen.add(ch); out+=chRules to remember
- 1Append on first sighting.
- 2Set tracks seen chars.
- 3Order preserved.
Use this pattern when
- First-occurrence dedup with order
Interview takeaway
First-occurrence-only = a seen set plus a builder.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternA core fresher pattern: Seen-set filtered build. Master it on small inputs and it transfers to harder problems.
Practice queueDirect variations and pattern siblings
Direct follow-ups