Introduction: One Insight Across Every Anagram Problem
Anagram problems appear across multiple LeetCode categories — string manipulation, hash maps, and sliding window — yet every single one reduces to the same underlying question: do two collections of characters have identical frequencies? Recognizing this unifying insight is what separates engineers who solve anagram problems effortlessly from those who treat each variant as a brand new challenge.
LeetCode hosts at least seven distinct anagram-flavored problems spanning Easy through Medium difficulty. They appear frequently in technical interviews at top companies because they test a candidate's ability to generalize from a concrete problem to an abstract pattern. The moment you see "rearrangement," "permutation," or "same characters different order," your mental model should immediately jump to frequency maps.
This guide organizes every major anagram problem into four techniques: validation, grouping, sliding window search, and harder variants. By the end you will have a mental framework that lets you identify, classify, and solve any anagram problem in an interview in under fifteen minutes.
All anagram problems reduce to comparing character frequency maps — whether validating, grouping, or searching. Internalizing this single statement is the entire lesson.
What Makes Something an Anagram Problem
Formally, two strings are anagrams if one is a rearrangement of the other. This means they must have exactly the same length and the same multiset of characters. The word "listen" is an anagram of "silent" because both contain exactly one l, one i, one s, one t, one e, and one n.
Anagram problems on LeetCode fall into three structural forms. The first form asks you to validate: are these two strings anagrams of each other? The second form asks you to group: given a list of strings, cluster all anagrams together. The third form asks you to find or count: given a long string and a pattern, find all positions where an anagram of the pattern starts.
The canonical solution to all three forms is the character frequency map — an array of 26 integers (for lowercase English letters) or a hash map indexed by character. Two strings are anagrams if and only if their frequency maps are identical. This O(k) comparison where k is the string length is both simpler and faster than sorting.
There are two common implementation strategies. The sorting approach sorts both strings and compares them lexicographically — O(k log k) per comparison, clean and readable. The frequency map approach builds counts in O(k) and compares in O(1) for fixed alphabets. For interview problems at scale (long strings, many comparisons), the frequency map is always superior.
- Validate: are these two strings anagrams? (#242, #383)
- Group: cluster a list of strings by their anagram class (#49)
- Find/Count: locate all starting positions of anagram windows (#438, #567)
- Harder variants: transform one string to be an anagram of another (#1347, #2273)
- Key invariant: two strings are anagrams iff their frequency maps are identical
Technique 1 — Validation (Easy): #242 and #383
Valid Anagram (LeetCode #242) is the canonical entry point. Given two strings s and t, return true if t is an anagram of s. The simplest correct approach sorts both strings and checks equality: sorted(s) == sorted(t) in Python. This is O(k log k) time and O(k) space for the sort buffer.
The optimized approach uses a single frequency array of 26 integers. Iterate through s, incrementing counts. Iterate through t, decrementing counts. If all 26 values are zero at the end, the strings are anagrams. This runs in O(k) time and O(1) space (since 26 is a constant). For the follow-up where characters can be Unicode, switch to a hash map.
Ransom Note (LeetCode #383) is a validation variant with an asymmetry: can you construct the ransom note using only letters from the magazine? You need every character in ransomNote to appear in magazine with at least as many occurrences. Build a frequency map of magazine, then decrement for each character in ransomNote. If any count goes negative, return false.
Both problems share the same core operation: build a frequency map and compare or check sufficiency. The only difference is symmetric equality (#242) versus one-sided sufficiency (#383). Recognizing this structural difference takes seconds once you have internalized the frequency map mental model.
Sorting O(k log k) vs Frequency Map O(k)
For validation problems, sorting gives O(k log k) time and is highly readable. The frequency array gives O(k) time and O(1) space (for fixed alphabets). In interview settings, mention both and then implement the frequency map version — it demonstrates deeper understanding and scales better to the sliding window variants.
Technique 2 — Grouping (Medium): #49 Group Anagrams
Group Anagrams (LeetCode #49) gives you a list of strings and asks you to cluster all anagrams together. For example, ["eat","tea","tan","ate","nat","bat"] groups into [["eat","tea","ate"],["tan","nat"],["bat"]].
The key insight is to use a canonical key that is identical for all anagrams in the same class. The simplest canonical key is the sorted string: "eat", "tea", and "ate" all sort to "aet". Use a hash map where each key maps to a list of strings. Iterate through the input, compute the sorted key for each string, and append the string to the appropriate bucket. Return the hash map values.
The sorting approach runs in O(n * k log k) where n is the number of strings and k is the maximum string length. An alternative canonical key uses the frequency tuple: count the 26 character frequencies and use the tuple (0,0,1,0,...) as the key. This reduces per-string work to O(k) for counting, giving O(n * k) total. However, tuple construction has higher constant factors and the sorting approach is usually preferred in interviews for clarity.
A subtle point: the problem guarantees lowercase English letters only, which means sorted strings are valid dictionary keys. If the input could contain arbitrary Unicode, you would need the frequency map approach or explicit encoding of the character counts as a string key.
Group Anagrams appears in almost every list of top 50 LeetCode interview questions. The pattern — use a canonical form as a hash key to group equivalent items — generalizes beyond anagrams to isomorphic strings, word patterns, and graph isomorphism checks.
- Canonical key option 1: sorted string — "eat" → "aet" (O(k log k) per string)
- Canonical key option 2: frequency tuple — "eat" → (1,0,0,1,1,...) (O(k) per string)
- Use a defaultdict(list) or equivalent to accumulate groups
- Return list(groups.values()) as the final answer
- Time: O(n * k log k) with sorting, O(n * k) with frequency tuple
Technique 3 — Sliding Window Search (Medium): #438 and #567
Find All Anagrams in a String (LeetCode #438) and Permutation in String (LeetCode #567) are structurally identical — #567 asks for a boolean while #438 collects all starting indices. Both give you a long string s and a pattern p, and ask whether any window in s is an anagram of p.
The naive approach checks every length-|p| window independently: O(n * k) total. The sliding window approach maintains a running frequency difference count and achieves O(n). The key data structure is a "diff" counter tracking how many characters currently have a mismatch between the window and the pattern.
Initialize the pattern frequency map. Initialize the window on the first |p| characters of s. For each character position, compute the initial diff count. Then slide the window one character at a time: add the new right character, remove the leftmost character. Update the diff count for each change. When diff == 0, the current window is an anagram — record the start index.
The diff optimization: instead of comparing the entire 26-element frequency arrays on every slide (O(26) = O(1) but with a larger constant), maintain a single integer counting how many characters have a nonzero difference. When a character's difference transitions to zero, decrement diff. When it transitions from zero, increment diff. The window is an anagram exactly when diff == 0.
The sliding window anagram search (#438, #567) runs in O(n) vs naive O(n * k) by maintaining a running frequency diff count. This is the critical optimization to articulate in interviews.
Frequency Diff Optimization
Track a single integer "diff" = number of characters with nonzero count difference between window and pattern. Increment diff when a character transitions from 0 to nonzero difference; decrement when it transitions from nonzero to 0. The window is an anagram when diff == 0. This turns each slide into O(1) work instead of O(26) array comparison.
Technique 4 — Harder Variants: #1347 and #2273
Minimum Number of Steps to Make Two Strings Anagram (LeetCode #1347) asks: given strings s and t of equal length, what is the minimum number of character replacements in t to make it an anagram of s? The answer is the number of characters in t that are "in excess" compared to s.
Build the frequency difference map: count[c] += 1 for each character in s, count[c] -= 1 for each character in t. The answer is the sum of all positive differences (equivalently, the sum of all negative differences, since the string lengths are equal). Characters in excess in t must be replaced, and their count equals the number of deficient characters in s.
Remove Anagrams (LeetCode #2273) gives you a list of words and asks you to repeatedly remove any word that is an anagram of its previous neighbor until no such pair exists. The order in which you process removals matters — you should scan left to right and remove a word if it is an anagram of the word immediately before it in the current list.
The efficient approach is a single left-to-right scan using a result stack. For each word, check if it is an anagram of the top of the stack (sort both or compare frequency maps). If yes, skip it (it gets removed). If no, push it onto the stack. Return the stack as the final list. This is O(m * k log k) where m is the number of words and k is the max word length.
Both #1347 and #2273 demonstrate that frequency maps are not just for equality checks — they also quantify the "distance" between two strings in terms of character composition. The difference of frequency maps tells you exactly how many substitutions or removals are needed.
- 1Build frequency map: count[c] += 1 for s, count[c] -= 1 for t
- 2Sum all positive values in the count map — that is your answer for #1347
- 3For #2273: scan left-to-right with a result stack
- 4At each word, compare sorted form (or frequency map) against stack top
- 5If anagram of stack top: skip (remove). Otherwise: push to stack
- 6Return the stack as the final cleaned list
Conclusion: Anagram Mastery in Two Steps
Every anagram problem on LeetCode is a frequency map problem in disguise. The four techniques — validation, grouping, sliding window search, and difference-based variants — cover the entire problem space. Mastering them means mastering a single underlying abstraction: the character frequency array.
The sliding window technique is the most interview-critical of the four because it combines the frequency map insight with the sliding window pattern, producing an O(n) solution that impresses interviewers at top companies. Practice #438 and #567 until the diff-tracking optimization is automatic.
For grouping problems like #49, the canonical key pattern generalizes across many hash map problems. Sorting a string to produce a key is a small leap away from using any canonical form — sorted edges in a graph, normalized coordinates in geometry, or reduced fractions in number theory.
The recommended drill order is: #242 (Valid Anagram) → #383 (Ransom Note) → #49 (Group Anagrams) → #567 (Permutation in String) → #438 (Find All Anagrams) → #1347 (Min Steps Anagram) → #2273 (Remove Anagrams). Each problem adds one layer of complexity on top of the previous. Work through them in order on YeetCode with spaced repetition to lock in the pattern permanently.