Check if Two Strings Are Anagrams — Sort vs Frequency Counter in Java
Fast recall
Quick revision
Core answer
Arrays.sort(a.toCharArray()) + Arrays.sort(b.toCharArray()) and compare. Time O(n log n) (sorting), space O(n) (char array copy). (2) Frequency counter: count char occurrences in a, decrement for b; if all counts end at 0, they're anagrams. Time O(n), space O(Σ) where Σ is alphabet size. For ASCII (common case), use int[26] (lowercase) or int[128] — O(1) space effectively. For Unicode, use HashMap. Frequency counter is the canonical interview answer: linear time, constant space, works for any alphabet. First check length: if a.length() != b.length(), immediately return false. Edge cases: empty strings (anagrams by definition — but depends on spec), case sensitivity (decide: 'Listen' and 'Silent' are anagrams if case-insensitive), non-letter characters (spaces, punctuation — strip or keep depending on context), Unicode (surrogates need careful handling). Variants: Find all anagrams of pattern in string (sliding window + frequency), Group anagrams (use sorted-string or frequency-tuple as key in HashMap), Valid anagram check for a stream of chars (maintain running frequency). Compare with isomorphic strings: isomorphic means 1:1 mapping of characters; different constraint. For production, pre-normalize (lowercase, strip whitespace) based on spec. Frequency counter with int[26] is the simplest, fastest, and most interview-friendly version for ASCII input.Whether the candidate knows both approaches, can compare complexity, handle length check early, and address edge cases (case sensitivity, Unicode, whitespace)
Not checking lengths first. Using sort when frequency would be O(n). Ignoring case sensitivity spec. Mishandling Unicode with char[] (surrogates)
Discuss the int[26] optimization for lowercase ASCII, mention Unicode surrogate-pair handling, extend to group-anagrams and find-all-anagrams problems, address normalization (case, whitespace, diacritics)
Interview-ready guide
Interview answer
Two main approaches
1. Frequency counter (preferred)
- Check lengths first; if different, false
- Array int[26] for lowercase ASCII (or int[128])
- For each char in s: increment; for each in t: decrement
- If all counts zero at end: anagram
- Time O(n), Space O(1) for ASCII
2. Sort and compare
- Sort both char arrays, compare
- Simpler, but O(n log n) time, O(n) space
- Acceptable for short strings
Always start with length check
- O(1) shortcut
- If lengths differ, return false immediately
Alphabet choices
ASCII lowercase
- int[26]
- s.charAt(i) - 'a'
- O(1) space
- Fastest
Full ASCII
- int[128]
- s.charAt(i) as index
- O(1) space
Unicode
- HashMap<Character, Integer>
- O(Σ) space (distinct chars)
- Slower due to hashing
Surrogate pairs (emoji)
- s.length() counts char units, not code points
- Iterate via s.codePoints() for full Unicode support
- Rare in interviews but real in production
Normalization (production)
- Case sensitivity:
.toLowerCase()if ignoring case - Whitespace:
.replaceAll("\\s+", "")if ignoring spaces - Punctuation:
.replaceAll("\\p{Punct}", "") - Diacritics: Normalizer.NFD + strip marks
- Decide based on spec
Edge cases
Empty strings
- "" and "": trivially anagrams (spec-dependent)
- "" and "a": length differs, false
Single character
- "a" and "a": true
- "a" and "b": false
Case sensitivity
- 'Listen' and 'Silent': case-sensitive false, case-insensitive true
- Clarify with interviewer
Whitespace
- 'a b c' and 'c b a': false if whitespace matters
- Typical anagram problems ignore whitespace
Null
- Throw or return false; decide and document
Variants
Group anagrams
- Given array of strings, group anagrams together
- Key: sorted string (O(k log k)) or frequency tuple (O(k))
- Frequency tuple is faster for long strings
- Store in HashMap<String, List
>
Find all anagrams of p in s
- Sliding window of size |p|
- Maintain frequency array
- Arrays.equals on int[26] is O(1) — effectively O(n) total
Valid anagram with frequencies
- Two multisets equal
- Same technique
Isomorphic strings (different concept)
- Characters map 1:1
- 'egg' and 'add' are isomorphic, not anagrams
- Different constraint
Common pitfalls
1. Not checking lengths first
- Unnecessary O(n) work
2. Using sort when frequency is O(n)
- Sort is O(n log n) — worse for long strings
3. Assuming ASCII when input is Unicode
- int[26] fails for non-letter
- Use HashMap
4. Surrogate pair bugs
- Emoji / rare chars use two char units
- Use codePoints() for safety
5. Ignoring case when required
- Clarify with interviewer
- Add .toLowerCase() if case-insensitive
6. Not handling whitespace / punctuation
- Normalize first in production
For interviews
- Recommend frequency counter with int[26]
- Start with length check
- Mention sort as simpler alternative
- Address Unicode if input is general
- Extend to group-anagrams if asked
Recommendation: For checking if two strings are anagrams, the frequency counter approach is the canonical interview answer — O(n) time, O(1) space for ASCII (with int[26]), linear and cache-friendly. Always start with a length check (O(1) shortcut for mismatches). Use int[26] for lowercase letters, int[128] for full ASCII, or a HashMapcodePoints() since char is 16-bit and can't hold all code points. Mention the sort-and-compare approach as simpler (4 lines) but O(n log n) and O(n) space — slower for long strings. For variants: group anagrams uses either a sorted string or a frequency tuple as a HashMap key; the frequency tuple is O(k) per key, faster for long strings. Find all anagrams of a pattern in a string uses a sliding window of size |p| with frequency matching. Always normalize according to spec: lowercase, strip whitespace, punctuation, and diacritics depending on the problem definition. Know the difference from isomorphic strings (1:1 character mapping, different constraint). The mental model: anagram check = equal frequency distributions; frequency counter makes this O(n) linear; length check is the cheap first gate. Once you've internalized the int[26] pattern, many string-frequency problems use the same template.
Check if Two Strings Are Anagrams — Sort vs Frequency Counter in Java
Direct Answer
Two strings are anagrams if they contain the same characters with the same frequencies, just in different order (e.g., 'listen' and 'silent'). Two main approaches: (1) Sort both and compare: Arrays.sort(a.toCharArray()) + Arrays.sort(b.toCharArray()) and compare. Time O(n log n) (sorting), space O(n) (char array copy). (2) Frequency counter: count char occurrences in a, decrement for b; if all counts end at 0, they're anagrams. Time O(n), space O(Σ) where Σ is alphabet size. For ASCII (common case), use int[26] (lowercase) or int[128] — O(1) space effectively. For Unicode, use HashMap<Character, Integer>. Frequency counter is the canonical interview answer: linear time, constant space, works for any alphabet. First check length: if a.length() != b.length(), immediately return false. Edge cases: empty strings (anagrams by definition — but depends on spec), case sensitivity (decide: 'Listen' and 'Silent' are anagrams if case-insensitive), non-letter characters (spaces, punctuation — strip or keep depending on context), Unicode (surrogates need careful handling). Variants: Find all anagrams of pattern in string (sliding window + frequency), Group anagrams (use sorted-string or frequency-tuple as key in HashMap), Valid anagram check for a stream of chars (maintain running frequency). Compare with isomorphic strings: isomorphic means 1:1 mapping of characters; different constraint. For production, pre-normalize (lowercase, strip whitespace) based on spec. Frequency counter with int[26] is the simplest, fastest, and most interview-friendly version for ASCII input.
Common Mistakes & Pitfalls
Not checking lengths first. Using sort when frequency would be O(n). Ignoring case sensitivity spec. Mishandling Unicode with char[] (surrogates)
Check your understanding
Answer these without looking back at the article.
- Why is frequency counter O(n) better than sort-and-compare O(n log n)?
- How do you handle Unicode / emoji in anagram checking?
- How would you group an array of strings by anagrams?
- What's the difference between anagrams and isomorphic strings?
- How would you find all anagrams of pattern P in string S?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.