## Hashing Trade O(n) memory for **O(1) average lookup**. The workhorse behind "have I seen this before?". --- ## Recognition - "Does X exist?" / "How many times?" → `Set` / `Map` - Pair matching (complement lookup) → map value → index - Grouping by a derived key → map key → bucket - Counting characters → frequency map --- ## Template — complement lookup (LC 1) ```js function twoSum(nums, target) { const seen = new Map(); // value -> index for (let i = 0; i < nums.length; i++) { const need = target - nums[i]; if (seen.has(need)) return [seen.get(need), i]; seen.set(nums[i], i); } } ``` One pass: check for the partner **before** inserting yourself. --- ## Template — grouping (LC 49) ```js function groupAnagrams(strs) { const groups = new Map(); for (const s of strs) { const key = [...s].sort().join(""); if (!groups.has(key)) groups.set(key, []); groups.get(key).push(s); } return [...groups.values()]; } ``` The whole trick is **choosing the canonical key**. --- ## Pitfalls - Frequency compare needs both directions (surplus *and* deficit) - Object keys coerce to strings — use `Map` for numbers - Hashing is O(1) *average*; keys must be cheap to compute --- ## Recall - Two Sum: why insert after the lookup, not before? - Group Anagrams: name two valid canonical keys - LC 128 Longest Consecutive: why check `!set.has(x - 1)` first? --- ## Drill - 217 Contains Duplicate · 242 Valid Anagram - 1 Two Sum · 49 Group Anagrams - 347 Top K Frequent · 383 Ransom Note - 205 Isomorphic Strings · 128 Longest Consecutive · 290 Word Pattern