Character Frequency
Java coding interview problem for Character Problems: Character Frequency.
Counting the frequency of characters is one of the most fundamental String interview problems.
Although it looks simple, this problem introduces several important concepts used throughout Data Structures and Algorithms.
It helps you understand:
- HashMap
- Arrays
- ASCII
- Unicode
- String Traversal
- Counting Algorithms
- Time Complexity
Many advanced interview problems are based on character frequency, including:
- Valid Anagram
- First Non-Repeating Character
- First Repeating Character
- Group Anagrams
- String Compression
- Minimum Window Substring
Understanding this problem makes many interview questions much easier.
Problem Statement
Given a string,
count how many times each character appears.
Example 1
Input
banana
Output
b → 1
a → 3
n → 2
Example 2
Input
programming
Output
p → 1
r → 2
o → 1
g → 2
a → 1
m → 2
i → 1
n → 1
Example 3
Input
hello world
Output
h → 1
e → 1
l → 3
o → 2
(space) → 1
w → 1
r → 1
d → 1
What is Character Frequency?
Character frequency simply means
How many times each character occurs inside a string.
Example
apple
Frequency
a → 1
p → 2
l → 1
e → 1
Another Example
mississippi
Frequency
m → 1
i → 4
s → 4
p → 2
Why is this Question Asked in Interviews?
Interviewers use this problem to evaluate your understanding of:
- HashMap
- Arrays
- Collections Framework
- Iteration
- Frequency Counting
- Time Complexity
It is also the foundation for dozens of advanced interview questions.
Real-World Applications
Frequency counting is used everywhere.
Text Analytics
Count letters and words.
Search Engines
Analyze search keyword frequencies.
Data Compression
Run-Length Encoding uses frequencies.
Natural Language Processing (NLP)
Count character and word occurrences.
Cyber Security
Analyze repeated patterns in passwords and logs.
Bioinformatics
Count DNA sequence frequencies.
Understanding Frequency Counting
Suppose we have
banana
Read one character at a time.
Initially
{}
Read
b
Store
b → 1
Read
a
Now
b → 1
a → 1
Read
n
Now
b → 1
a → 1
n → 1
Read
a
Already exists.
Increase count.
a → 2
Continue until the end.
Final
b → 1
a → 3
n → 2
Frequency Table Visualization
Input
banana
| Character | Count |
|---|---|
| b | 1 |
| a | 3 |
| n | 2 |
Another Example
Input
apple
| Character | Count |
|---|---|
| a | 1 |
| p | 2 |
| l | 1 |
| e | 1 |
Mathematical Concept
Frequency can be represented as
Frequency(Character)
=
Number of Occurrences
For every character
Frequency
=
Previous Count
+
1
Example
banana
a
↓
1
↓
2
↓
3
ASCII Visualization
Input
code
Traversal
c
↓
Count = 1
o
↓
Count = 1
d
↓
Count = 1
e
↓
Count = 1
Input
google
Traversal
g
↓
1
o
↓
1
o
↓
2
g
↓
2
Dry Run
Input
banana
Current Map
{}
Read
b
{b=1}
Read
a
{b=1,a=1}
Read
n
{b=1,a=1,n=1}
Read
a
{b=1,a=2,n=1}
Read
n
{b=1,a=2,n=2}
Read
a
{b=1,a=3,n=2}
Approach 1 — Using HashMap (Recommended)
This is the most common interview solution.
The idea is simple.
- Traverse the string.
- Store every character in a HashMap.
- Increment its frequency whenever it appears again.
Why HashMap?
HashMap provides nearly constant-time insertion and lookup.
Example
banana
HashMap
b → 1
a → 3
n → 2
Algorithm
- Create a HashMap.
- Traverse every character.
- Check if the character already exists.
- Increment its frequency.
- Print the map.
Java Program
import java.util.HashMap;
import java.util.Map;
public class CharacterFrequencyHashMap {
public static void countFrequency(String text) {
Map<Character, Integer> map =
new HashMap<>();
for (char ch : text.toCharArray()) {
map.put(ch,
map.getOrDefault(ch, 0) + 1);
}
for (Map.Entry<Character, Integer> entry
: map.entrySet()) {
System.out.println(
entry.getKey() +
" -> " +
entry.getValue());
}
}
public static void main(String[] args) {
countFrequency("banana");
}
}
Output
b -> 1
a -> 3
n -> 2
Step-by-Step Code Explanation
Create the HashMap.
Map<Character, Integer> map =
new HashMap<>();
Traverse the string.
for(char ch : text.toCharArray())
Update frequency.
map.put(ch,
map.getOrDefault(ch,0)+1);
Example
banana
Processing
b → 1
a → 1
n → 1
a → 2
n → 2
a → 3
Print the result.
for(Map.Entry<Character,Integer> entry
: map.entrySet())
Dry Run of HashMap Approach
Input
apple
| Character | HashMap |
|---|---|
| a | {a=1} |
| p | {a=1,p=1} |
| p | {a=1,p=2} |
| l | {a=1,p=2,l=1} |
| e | {a=1,p=2,l=1,e=1} |
Advantages
- Easy to understand.
- Most common interview solution.
- Supports Unicode characters.
- Dynamic size.
- Linear time complexity.
Drawbacks
- Additional memory required.
- Output order is not guaranteed.
Approach 2 — Using Frequency Array (ASCII)
If the input contains only ASCII characters,
using an array is faster than a HashMap.
Each character value acts as the array index.
Visualization
Input
banana
ASCII Array
Index('a') = 97
↓
3
Index('b') = 98
↓
1
Index('n') = 110
↓
2
Algorithm
- Create an integer array of size 256.
- Traverse the string.
- Increment frequency.
- Traverse the array.
- Print non-zero values.
Java Program
public class CharacterFrequencyArray {
public static void countFrequency(String text) {
int[] frequency =
new int[256];
for (char ch : text.toCharArray()) {
frequency[ch]++;
}
for (int i = 0; i < frequency.length; i++) {
if (frequency[i] > 0) {
System.out.println(
(char) i +
" -> " +
frequency[i]);
}
}
}
public static void main(String[] args) {
countFrequency("banana");
}
}
Output
a -> 3
b -> 1
n -> 2
Step-by-Step Code Explanation
Create array.
int[] frequency =
new int[256];
Each position represents one ASCII character.
Update frequency.
frequency[ch]++;
Print values.
if(frequency[i] > 0)
Display
Character
↓
Frequency
Time & Space Complexity
| Approach | Time | Extra Space |
|---|---|---|
| HashMap | O(n) | O(k) |
| Frequency Array | O(n) | O(1)* |
Where:
- n = Length of the string
- k = Number of distinct characters
*For a fixed ASCII character set, the array size is constant (256), so the extra space is considered O(1).
Comparison of Approaches
| Feature | HashMap | Frequency Array |
|---|---|---|
| Interview Friendly | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Easy to Understand | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Performance | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Supports Unicode | ⭐⭐⭐⭐⭐ | Limited (ASCII example) |
Advantages
- Both approaches have O(n) time complexity.
- HashMap supports dynamic character sets and Unicode.
- Frequency Array is extremely fast for ASCII strings.
- Both are widely accepted interview solutions.
Drawbacks
- HashMap uses additional memory.
- Frequency Array is limited to fixed-size character sets unless adapted.
- HashMap does not preserve insertion order.
In Part 2, we'll cover:
- Approach 3 – Using LinkedHashMap (Maintain Insertion Order)
- Approach 4 – Using Java Streams
- Approach 5 – Using TreeMap (Sorted Output)
- Unicode Considerations
- Comparison of All Approaches
- Common Interview Mistakes
- Edge Cases
- Interview Follow-up Questions
- Related Problems
- Key Takeaways
- Frequently Asked Interview Questions
- Interview Tips
Approach 3 — Using LinkedHashMap (Maintain Insertion Order)
A LinkedHashMap is an extension of HashMap that preserves the order in which keys are inserted.
This is useful when the output must appear in the same order as the original string.
Why LinkedHashMap?
Example
banana
Insertion Order
b
a
n
Output
b -> 1
a -> 3
n -> 2
Unlike HashMap, the order is preserved.
Algorithm
- Create a LinkedHashMap.
- Traverse the string.
- Update character frequency.
- Print the map.
Java Program
import java.util.LinkedHashMap;
import java.util.Map;
public class CharacterFrequencyLinkedHashMap {
public static void countFrequency(String text) {
Map<Character, Integer> map =
new LinkedHashMap<>();
for (char ch : text.toCharArray()) {
map.put(ch,
map.getOrDefault(ch, 0) + 1);
}
for (Map.Entry<Character, Integer> entry
: map.entrySet()) {
System.out.println(
entry.getKey() +
" -> " +
entry.getValue());
}
}
public static void main(String[] args) {
countFrequency("banana");
}
}
Output
b -> 1
a -> 3
n -> 2
Advantages
- Preserves insertion order.
- Easy to understand.
- Excellent interview solution.
Drawbacks
- Slightly slower than HashMap.
- Uses additional memory.
Approach 4 — Using Java Streams
Java 8 Streams provide a concise functional programming solution.
Instead of manually iterating,
Streams group characters and count their occurrences.
Algorithm
- Convert the string into a character stream.
- Group characters.
- Count each occurrence.
- Print the result.
Java Program
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class CharacterFrequencyStreams {
public static void countFrequency(String text) {
Map<Character, Long> frequency =
text.chars()
.mapToObj(ch -> (char) ch)
.collect(Collectors.groupingBy(
Function.identity(),
LinkedHashMap::new,
Collectors.counting()));
frequency.forEach(
(key, value) ->
System.out.println(
key + " -> " + value));
}
public static void main(String[] args) {
countFrequency("banana");
}
}
Output
b -> 1
a -> 3
n -> 2
Advantages
- Modern Java style.
- Very concise.
- Demonstrates Java Streams.
Drawbacks
- More difficult for beginners.
- Additional Stream overhead.
- Not usually preferred during coding interviews.
Approach 5 — Using TreeMap (Sorted Output)
Sometimes interviewers ask for the output to be sorted alphabetically.
TreeMap automatically sorts keys.
Visualization
Input
banana
TreeMap
a -> 3
b -> 1
n -> 2
Notice
Keys are sorted alphabetically.
Algorithm
- Create TreeMap.
- Traverse string.
- Update frequency.
- Print TreeMap.
Java Program
import java.util.Map;
import java.util.TreeMap;
public class CharacterFrequencyTreeMap {
public static void countFrequency(String text) {
Map<Character, Integer> map =
new TreeMap<>();
for (char ch : text.toCharArray()) {
map.put(ch,
map.getOrDefault(ch, 0) + 1);
}
for (Map.Entry<Character, Integer> entry
: map.entrySet()) {
System.out.println(
entry.getKey() +
" -> " +
entry.getValue());
}
}
public static void main(String[] args) {
countFrequency("banana");
}
}
Output
a -> 3
b -> 1
n -> 2
Advantages
- Automatically sorts output.
- Useful for alphabetical reports.
- No extra sorting required.
Drawbacks
- Slower than HashMap.
- Tree operations take O(log k).
Unicode Considerations
Java String objects use UTF-16 encoding.
Examples
こんにちは
नमस्ते
😊😂😊
The following approaches support general Java strings:
- HashMap
- LinkedHashMap
- TreeMap
For supplementary Unicode characters (such as many emoji), iterate over Unicode code points instead of individual char values.
Edge Cases
| Input | Expected Output |
|---|---|
"" |
No Characters |
"a" |
a → 1 |
"aaaa" |
a → 4 |
"AaAa" |
A → 2, a → 2 (case-sensitive) |
" " |
(space) → 1 |
null |
Handle appropriately based on application requirements |
Time & Space Complexity
| Approach | Time | Extra Space |
|---|---|---|
| HashMap | O(n) | O(k) |
| Frequency Array | O(n) | O(1)* |
| LinkedHashMap | O(n) | O(k) |
| Java Streams | O(n) | O(k) |
| TreeMap | O(n log k) | O(k) |
Where:
- n = Length of the string
- k = Number of distinct characters
*For a fixed ASCII character set, the array size is constant (256), so the extra space is considered O(1).
Comparison of All Approaches
| Approach | Interview Friendly | Performance | Maintains Order | Sorted Output | Best Use Case |
|---|---|---|---|---|---|
| HashMap | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ❌ | ❌ | General interviews |
| Frequency Array | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ❌ | ❌ | ASCII strings |
| LinkedHashMap | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ✅ | ❌ | Maintain insertion order |
| Java Streams | ⭐⭐⭐⭐ | ⭐⭐⭐ | ✅ | ❌ | Modern Java applications |
| TreeMap | ⭐⭐⭐⭐ | ⭐⭐⭐ | ❌ | ✅ | Sorted reports |
Common Interview Mistakes
Mistake 1
Using HashMap when insertion order is required.
Example
banana
Expected
b
a
n
Use LinkedHashMap.
Mistake 2
Using a Frequency Array for Unicode strings.
ASCII arrays work only for fixed-size character sets.
Mistake 3
Forgetting case sensitivity.
Example
A
a
These are different characters.
Mistake 4
Ignoring whitespace.
Input
hello world
The space is also a valid character.
Mistake 5
Using nested loops.
for(...)
for(...)
This leads to
O(n²)
HashMap provides an
O(n)
solution.
Interview Follow-up Questions
Q1. Why is HashMap preferred?
Q2. When should LinkedHashMap be used?
Q3. Why is TreeMap slower?
Q4. Which solution is fastest?
Q5. How would you support Unicode?
Q6. Can this be solved without collections?
Q7. What if the output must be sorted?
Q8. How would you process billions of characters?
Q9. What is the difference between HashMap and LinkedHashMap?
Q10. What is the space complexity?
Related Problems
- First Non-Repeating Character
- First Repeating Character
- Valid Anagram
- Group Anagrams
- Remove Duplicate Characters
- String Compression
- Longest Substring Without Repeating Characters
- Minimum Window Substring
Key Takeaways
- Character frequency counting is the foundation of many string interview problems.
- HashMap is the most common interview solution because it is simple, flexible, and runs in O(n) time.
- Frequency Array is the fastest option for ASCII input.
- LinkedHashMap preserves insertion order, making it ideal when output order matters.
- TreeMap automatically sorts characters alphabetically but has O(log k) insertion time.
- Java Streams provide a concise functional programming alternative.
Frequently Asked Interview Questions
Q1. Which approach is best for interviews?
HashMap is the preferred interview solution because it is easy to explain, efficient, and supports all common character sets.
Q2. Which solution is fastest?
For ASCII input,
the Frequency Array approach is typically the fastest because array indexing is constant time.
Q3. When should I use LinkedHashMap?
Use LinkedHashMap when you must preserve the order in which characters first appear.
Example
banana
Output
b -> 1
a -> 3
n -> 2
Q4. When should I use TreeMap?
Use TreeMap when the output needs to be sorted alphabetically without calling an additional sorting method.
Q5. Does HashMap preserve order?
No.
HashMap does not guarantee insertion order.
Use LinkedHashMap for insertion order or TreeMap for sorted order.
Interview Tip
If an interviewer asks:
"Count the frequency of each character in a string."
Start with the HashMap solution because it is the industry-standard answer.
Then discuss progressively specialized approaches:
- HashMap (recommended)
- Frequency Array (ASCII optimization)
- LinkedHashMap (maintain insertion order)
- Java Streams (functional programming)
- TreeMap (sorted output)
Before coding, clarify requirements such as:
- Is the input limited to ASCII or does it include Unicode?
- Should uppercase and lowercase letters be treated differently?
- Should spaces and punctuation be counted?
- Does the output need to preserve insertion order or be sorted?
These questions demonstrate strong problem-solving skills and interview readiness while showing that you understand the trade-offs between different Java collection classes.