C++ Program to Remove Duplicates from String
std::unordered_set to track seen characters and build a new string with only unique characters, like this: iterate over the original string, add unseen characters to the result, and skip duplicates.Examples
How to Think About It
Algorithm
Code
#include <iostream> #include <unordered_set> #include <string> int main() { std::string input = "programming"; std::unordered_set<char> seen; std::string result; for (char c : input) { if (seen.find(c) == seen.end()) { seen.insert(c); result += c; } } std::cout << result << std::endl; return 0; }
Dry Run
Let's trace the input "programming" through the code
Start with empty set and result
seen = {}, result = ""
Process 'p'
'p' not in seen, add 'p' to seen and result seen = {'p'}, result = "p"
Process 'r'
'r' not in seen, add 'r' seen = {'p','r'}, result = "pr"
Process 'o'
'o' not in seen, add 'o' seen = {'p','r','o'}, result = "pro"
Process 'g'
'g' not in seen, add 'g' seen = {'p','r','o','g'}, result = "prog"
Process 'r'
'r' already in seen, skip seen = {'p','r','o','g'}, result = "prog"
Process 'a'
'a' not in seen, add 'a' seen = {'p','r','o','g','a'}, result = "proga"
Process 'm'
'm' not in seen, add 'm' seen = {'p','r','o','g','a','m'}, result = "progam"
Process 'm'
'm' already in seen, skip seen = {'p','r','o','g','a','m'}, result = "progam"
Process 'i'
'i' not in seen, add 'i' seen = {'p','r','o','g','a','m','i'}, result = "progami"
Process 'n'
'n' not in seen, add 'n' seen = {'p','r','o','g','a','m','i','n'}, result = "progamin"
Process 'g'
'g' already in seen, skip seen = {'p','r','o','g','a','m','i','n'}, result = "progamin"
| Character | Seen Set | Result String |
|---|---|---|
| p | {p} | p |
| r | {p,r} | pr |
| o | {p,r,o} | pro |
| g | {p,r,o,g} | prog |
| r | {p,r,o,g} | prog |
| a | {p,r,o,g,a} | proga |
| m | {p,r,o,g,a,m} | progam |
| m | {p,r,o,g,a,m} | progam |
| i | {p,r,o,g,a,m,i} | progami |
| n | {p,r,o,g,a,m,i,n} | progamin |
| g | {p,r,o,g,a,m,i,n} | progamin |
Why This Works
Step 1: Use a set to track seen characters
A std::unordered_set stores characters already encountered, allowing quick checks to avoid duplicates.
Step 2: Build result with unique characters
Only characters not in the set are added to the result string, preserving the order of first appearance.
Step 3: Skip duplicates efficiently
If a character is already in the set, it is skipped, so duplicates are removed without extra loops.
Alternative Approaches
#include <iostream> #include <string> int main() { std::string input = "hello"; std::string result; for (char c : input) { if (result.find(c) == std::string::npos) { result += c; } } std::cout << result << std::endl; return 0; }
#include <iostream> #include <string> #include <algorithm> int main() { std::string input = "programming"; std::sort(input.begin(), input.end()); auto last = std::unique(input.begin(), input.end()); input.erase(last, input.end()); std::cout << input << std::endl; return 0; }
Complexity: O(n) time, O(n) space
Time Complexity
The program loops through the string once, and each set insertion and lookup is O(1) on average, so total time is O(n).
Space Complexity
Extra space is used for the set and the result string, both up to size n in the worst case.
Which Approach is Fastest?
Using an unordered_set is faster than searching the result string each time, and preserves order unlike sorting.
| Approach | Time | Space | Best For |
|---|---|---|---|
| unordered_set tracking | O(n) | O(n) | Fast removal preserving order |
| string find method | O(n^2) | O(n) | Simple code, small strings |
| sort + unique | O(n log n) | O(1) | When order does not matter |