Trade space for speed. Store values by key so you can look them up in O(1) instead of scanning.
For each number, check if its complement is already in the map. If not, store the number and its index. One pass, O(n).
Check: is 18 - 2 = 16 in the map? No. Store 2 → index 0.
A hash function converts a key into a bucket index. Different keys can land in the same bucket (collision), but on average each lookup touches one bucket. That's why it's O(1).
A Set is a Map without values — just keys. Three operations: add, has, delete. All O(1).
Map pattern
function twoSum( nums: number[], target: number) { const map = new Map<number, number>() for (let i = 0; i < nums.length; i++) { const complement = target - nums[i] if (map.has(complement)) return [map.get(complement)!, i] map.set(nums[i], i) } }
Set pattern
function hasDuplicate( nums: number[]) { const seen = new Set<number>() for (const n of nums) { if (seen.has(n)) return true seen.add(n) } return false }
Frequency counting
function topKFrequent( nums: number[], k: number) { const freq = new Map<number, number>() for (const n of nums) freq.set(n, (freq.get(n) ?? 0) + 1) return [...freq] .sort((a, b) => b[1] - a[1]) .slice(0, k) .map(([num]) => num) }
O(n) time, O(n) space