File: design-hashset/solution.py

Date: 2026-06-06

Time: 16:18

design-hashset/solution.py

Purpose

This file implements LeetCode 705 — Design HashSet. It provides a from-scratch hash set (no built-in set) that supports add, remove, and contains on integer keys in the range [0, 10^6]. The file is self-contained: implementation and unit tests live together.

Key Components

MyHashSet — The hash set class, backed by a fixed-size array of buckets (separate chaining).

| Member | Contract |

|--------|----------|

| numbuckets = 769 | Bucket count. A prime, which reduces collision clustering for modular hashing. |

| _buckets: list[list[int]] | Array of 769 independent lists. Each list holds keys that hash to that index. |

| _hash(key) -> int | Maps a key to a bucket index via key % 769. |

| add(key) | Appends key to its bucket only if not already present. Guarantees no duplicates within a bucket. |

| remove(key) | Removes key from its bucket. No-op if absent — never raises. |

| contains(key) -> bool | Linear scan of the bucket for membership. |

TestMyHashSet — Six test cases covering the LeetCode example, duplicate adds, remove-of-absent-key, boundary values (0 and 10^6), hash collisions (0 and 769), and empty-set lookup.

Patterns

Dependencies

Flow

1. Init: _init_ creates 769 empty lists — one per bucket.

2. Add: _hash computes the bucket index → linear scan of that bucket with in → append if absent.

3. Remove: Same hash → linear scan with inlist.remove() if found.

4. Contains: Same hash → in operator on the bucket list → return boolean.

All three public methods are O(n/k) average where n is the number of stored keys and k is 769, degrading to O(n) worst-case if all keys collide.

Invariants

Error Handling

There is none — by design. The LeetCode contract guarantees keys are non-negative integers in [0, 10^6], so no input validation is performed. remove silently does nothing for absent keys rather than raising KeyError.