The problem. Given two strings s and t of lowercase letters, return true if t is an anagram of s — the same letters, each used the same number of times, in any order.
s = "listen", t = "silent" -> true
s = "anagram", t = "nagaram" -> true
s = "rat", t = "car" -> false ("t" in one, "c" in the other)Many string questions don't care about order at all — only about how many of each character there are. Anagrams, "can you build the ransom note from the magazine", "find the first character that appears once", "group words with the same letters". The pattern: count the characters, then answer the question from the counts.
The counter is chosen by the alphabet, as the memory lesson showed. For lowercase English letters, an int[26] indexed by ch - 'a' is the fastest and smallest. For any characters at all, use a hash map from character to count. Either way, counting a string of length n is one pass: O(n).
Anagrams contain the same letters, so after sorting they are the same string.
function isAnagram(s, t) { if (s.length !== t.length) return false; const sorted = (x) => [...x].sort().join(""); return sorted(s) === sorted(t); // anagrams sort to the same string}Time O(n log n), space O(n). Sorting dominates; the sorted copies take O(n) (C++ sorts the copies it was given).
Use a single array of 26 counters: every letter of s adds one, every letter of t takes one away. If the strings are anagrams, everything cancels and all 26 counters end at zero.
s adds, t subtracts; anagrams leave every counter at 0. Try rat and car.
function isAnagram(s, t) { if (s.length !== t.length) return false; // different lengths can't match const count = new Array(26).fill(0); for (let i = 0; i < s.length; i++) { count[s.charCodeAt(i) - 97]++; // s adds one count[t.charCodeAt(i) - 97]--; // t takes one away } return count.every((c) => c === 0); // every letter balanced out?}Time O(n), space O(1). One pass over both strings and a final check of 26 counters, which is constant however long the strings are.
The classic follow-up: what if the strings contain any Unicode characters? Then 26 slots aren't enough — swap the array for a hash map from character to count. The algorithm doesn't change.
false straight away."aab" and "abb": false. Counting catches this; checking only which letters appear does not.note be built from the letters of magazine? Count the magazine, then spend letters for the note; a counter going negative means no.t is s shuffled with one extra letter: the counter that ends at -1 is it (or XOR all the characters).