一键导入
algo-hash
Hash maps and sets — when O(1) lookup pays off, hash collisions, frozen keys, and hashing custom types.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Hash maps and sets — when O(1) lookup pays off, hash collisions, frozen keys, and hashing custom types.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Breadth-first search — shortest path on unweighted graphs, level-order traversal, and the `visited` discipline that prevents O(2^n) blowups.
Binary search invariants, half-open intervals, and the `lo<hi` template that beats off-by-one bugs.
Depth-first search — recursive vs iterative, recursion-depth gotchas, three-color cycle detection, topological sort.
Dynamic programming — state design, memoization vs tabulation, dimension-reduction, and when DP is the wrong tool.
Pick the right traversal — BFS for unweighted shortest path, Dijkstra for weighted, A* for goal-directed, 0/1-BFS for binary weights.
Greedy algorithms — exchange-argument proofs, when greedy beats DP, classic patterns (interval scheduling, Huffman, scheduling).
| name | algo-hash |
| description | Hash maps and sets — when O(1) lookup pays off, hash collisions, frozen keys, and hashing custom types. |
| when-to-use | Frequency counts, deduplication, two-sum and complement-lookup patterns, anagram grouping, prefix-sum + hash. |
Hashing trades memory for time. The trade is almost always worth it when you need membership / count / lookup by key. The dangerous failure mode is hashing a mutable type — Python silently breaks, JavaScript happily compares by reference instead of value.
O(1) insert / lookup / delete for keys with a
good hash distribution.dict, but never rely on it
for correctness — sort explicitly when order matters.tuple of hashables OK;
list, dict, set are not hashable.O(1) average, O(n) worst case
under adversarial collisions.O(n).O(n) for n distinct keys; load factor < 0.75 for
reasonable performance.def two_sum(nums: list[int], target: int) -> tuple[int, int] | None:
"""Indices (i, j) such that nums[i] + nums[j] == target, i < j."""
seen: dict[int, int] = {} # value -> first index
for j, x in enumerate(nums):
complement = target - x
if complement in seen:
return (seen[complement], j)
seen.setdefault(x, j)
return None
The complement-lookup pattern generalises: any "find pair s.t.
f(a, b) == target" reduces to "store seen f results, look up
the inverse." The same shape gives prefix-sum + hash for
"subarrays summing to k."
function groupAnagrams(words) {
const groups = new Map();
for (const w of words) {
// Sorted-letter signature is a canonical key for anagrams.
const key = [...w].sort().join("");
if (!groups.has(key)) groups.set(key, []);
groups.get(key).push(w);
}
return [...groups.values()];
}
Map is the right choice over a plain {} when keys are not
strings or when you need a defined iteration order. Set is the
right choice when you only care about membership.
list raises TypeError
on insertion. A custom class is hashable by default (id-based)
but compares by == only if you implement __eq__ and
__hash__ together — missing the pair gives baffling lookup
failures.{} vs set() in Python. {} is an empty dict, not a set;
set() is empty set. Easy to write seen = {} then call
seen.add(x) and crash.dict.get(k, []) returns a fresh list
each call. Use dict.setdefault or collections.defaultdict
when accumulating.{}. Coerced to string. Use
Map for non-string keys.NaN != NaN in both languages, so NaN-
keyed lookups can fail mysteriously.__eq__ / __hash__ contract.The "store seen, look up complement" pattern shows up in two-sum, 3-sum, contiguous-subarray-sum-equals-k, longest-substring-without- repeats, and dozens more. Recognise the shape and you skip the quadratic version.