Group Anagrams
Frequency-signature grouping
The leap: using a sorted string as a HashMap KEY. Creative key design is a core skill.
Problem
Given an array of strings strs, group the anagrams together. You may return the answer in any order.
Intuition
The grouping key cannot be the raw string, because "eat" and "tea" should land in the same bucket.
What is identical for all anagrams? Their character counts.
So the problem becomes: build a canonical signature for each string, then hash by that signature. Sorting each string works, but because the alphabet is lowercase English letters, a 26-count signature is cheaper and more direct.
Approach
Count-Signature HashMap
O(n * k)O(n * k)For each string:
- Count the occurrences of each letter.
- Use that 26-slot count vector as the map key.
- Push the original string into that bucket.
At the end, return all buckets.
use std::collections::HashMap;
impl Solution {
pub fn group_anagrams(strs: Vec<String>) -> Vec<Vec<String>> {
let mut groups: HashMap<[u8; 26], Vec<String>> = HashMap::new();
for s in strs {
let mut key = [0u8; 26];
for &b in s.as_bytes() {
key[(b - b'a') as usize] += 1;
}
groups.entry(key).or_default().push(s);
}
groups.into_values().collect()
}
}
function groupAnagrams(strs: string[]): string[][] {
const groups = new Map<string, string[]>();
for (const s of strs) {
const count = new Array<number>(26).fill(0);
for (let i = 0; i < s.length; i++) {
count[s.charCodeAt(i) - 97]++;
}
const key= count.join("#");
if (!groups.has(key)) groups.set(key, []);
groups.get(key)!.push(s);
}
return Array.from(groups.values());
}Language notes:
- Rust —
[u8; 26]is hashable and comparable, so it works directly as aHashMapkey with no string allocation. - TypeScript — arrays are not value-equal keys in
Map, so serialize the count vector into a stable string key.
Edge cases
- Single string — it forms a one-element group.
- Empty string — its signature is 26 zeros; all empty strings belong together.
- Different group order — the problem allows any ordering of groups and words within groups.
Takeaway
A good hash key is often the whole problem.
For #49, the hard part is not the map itself. It is inventing a key that captures "anagram equivalence" exactly. That is a recurring design move in hash-based problems.
More in Arrays & Hashing
HashMap lookup. The most fundamental pattern: trade space for time.
HashSet existence check. Think about why this is O(n) not O(n²).
Frequency counting with a fixed-size array or HashMap.
Only start counting from sequence beginnings. Think before you loop.