String · 3 of 43
Find Duplicate characters in a string
Find every letter that shows up more than once in a string, and how many times, by keeping a tally sheet as you read.
- Simple way
- time O(n^2)
room O(n) - Clever way
- time O(n)
room O(k)
The problem, simply
You get a string. Find every character that appears more than once, and say how many times it appears. List them in the order they first show up in the string.
Capital and small letters are different characters unless the interviewer says otherwise.
A story to remember it
Picture it
programming has 11 letters. r, g and m each show up twice, and every other letter shows up once.
- looking now
- checking
- answer
Examples
A normal word
- In
s = 'programming'- Out
r 2, g 2, m 2
r first shows up at spot 1, g at spot 3 and m at spot 6, so that is the order.
One duplicate
- In
s = 'hello'- Out
l 2
Only l repeats.
No duplicates
- In
s = 'abc'- Out
(nothing)
Every letter is used once. Return an empty answer.
All the same
- In
s = 'aaaa'- Out
a 4
One letter, four times.
Case matters
- In
s = 'Aa'- Out
(nothing)
A and a are different characters, unless you are told to ignore case.
Way 1: the simple way
For each letter, walk the rest of the string and count its copies. Mark every copy you find so you do not count the same letter again later.
- For each spot
ithat is not marked, count how many later spotsjhold the same letter, and mark them. - If the count is more than 1, write down the letter and its count.
import java.util.*;
class Solution {
public Map<Character, Integer> duplicates(String s) {
Map<Character, Integer> out = new LinkedHashMap<>();
boolean[] counted = new boolean[s.length()];
for (int i = 0; i < s.length(); i++) {
if (counted[i]) continue; // this letter is already done
int count = 1;
for (int j = i + 1; j < s.length(); j++) {
if (s.charAt(j) == s.charAt(i)) {
count++;
counted[j] = true; // do not count this copy again
}
}
if (count > 1) out.put(s.charAt(i), count);
}
return out;
}
}How long it takes: for each letter we may walk the whole rest of the string, O(n^2). Extra room: the marks, O(n).
Way 2: the clever way
Keep a tally sheet. In code it is an array of 256 counters, one per character, or a hash map when the characters can be anything.
- Read the string once. For each character
c, add 1 tocount[c]. - Read the string a second time. When you meet a character whose count is more than 1, write it down with its count, then set its count to 0 so you do not write it again.
The tally sheet fills up as we read programming
01 / 13
An empty tally sheet. We read programming one letter at a time and add a mark next to that letter.
- looking now
- checking
- seen
- answer
- just added
- ignored
import java.util.*;
class Solution {
public Map<Character, Integer> duplicates(String s) {
int[] count = new int[256]; // one counter per character
for (int i = 0; i < s.length(); i++) count[s.charAt(i)]++;
Map<Character, Integer> out = new LinkedHashMap<>();
for (int i = 0; i < s.length(); i++) { // second walk keeps first seen order
char c = s.charAt(i);
if (count[c] > 1) {
out.put(c, count[c]);
count[c] = 0; // report each letter once
}
}
return out;
}
}How long it takes: two walks over the string, O(n). Extra room: one counter per possible character, O(k), where k is the alphabet size. For 256 characters that is a fixed size.
Watch out for
- A
HashMapdoes not keep insertion order. UseLinkedHashMap, or walk the string again as above, if order matters. int[256]crashes on any character above 255, like the euro sign or an emoji. Useint[65536]or aHashMap<Character, Integer>for any text.- Spaces count as characters too.
a b chas two spaces. Ask whether to skip them.
What interviewers ask next
- Can you do it with no extra counters? Sort the characters first, then equal letters sit next to each other and you count runs. That is
O(n log n)time, and it loses the original order. - Only lowercase
atozand no extra room at all? Use the 26 bits of oneintas "seen once" flags and anotherintas "seen twice" flags. This finds which letters repeat, but not how many times. - First character that does not repeat? Same tally sheet, then walk the string and return the first letter with count 1.
- Are two strings anagrams? Add 1 for each letter of the first, take 1 for each letter of the second, then check that every counter is 0.
Remember this
Grown-up words: the tally sheet is a frequency table, stored as a count array or a hash map, reading it in first seen order uses a LinkedHashMap or a second pass, and k is the alphabet size.