Skip to content
Hello Python
Data Structure1 Practice4 Interview

Hash Set

Unique-key structure for average constant-time membership and duplicate detection. This guide turns that contract into deliberate Python operations, interview invariants, and a runnable practice loop.

Recognize it when

Consider Hash Set when the prompt's constraints and required operations match this shape: Unique-key structure for average constant-time membership and duplicate detection.

Pybit studies a professional Hash Set interview workspace with precise technical objects.
On this page · Mental Model

Checking your account…

Sign in to save your code and progress across devices. The lesson and problem statement remain public.

Hash Set Code Labs

Mental Model

A set answers whether a distinct hashable value is present. It deliberately stores no attached count, index, or payload. This narrower contract makes intent clearer than a dictionary whose values are meaningless placeholders.

Presence Without Attached Values

Python set supports expected O(1) membership, insertion, and removal under ordinary hashing. Keys must be hashable and keep stable equality/hash behavior while stored. Lists and sets are mutable and cannot be members; use a tuple or frozenset only when that immutable representation matches the problem’s equality rule.

The set documentation(opens in a new tab) defines add, discard, remove, and algebra operations. discard tolerates absence; remove raises KeyError when absence violates the contract.

Track Seen State in One Pass

Test membership before insertion when the output asks whether a value appeared earlier. The invariant is that seen contains exactly the distinct values from the processed prefix. Inserting first would make every current value appear duplicated by itself.

Flag Previously Seen Values

Reference
def track_seen_values(values):
    seen = set()
    result = []
    for value in values:
        result.append(value in seen)
        seen.add(value)
    return result
Practice

Implement track_seen_values(values). Return true exactly when the current value appeared at an earlier index, before adding the current occurrence.

Public tests

  • Verify earlier occurrence semantics

Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor

Apply Set Algebra

Intersection expresses “in both,” difference expresses “only on this side,” and union expresses “in either.” These operations return sets and therefore discard duplicates and sequence order. Convert to a sorted list only when the output contract needs deterministic ordering.

Compute Set Relationships

Reference
def set_relationships(left, right):
    left_set = set(left)
    right_set = set(right)
    return (
        sorted(left_set & right_set),
        sorted(left_set - right_set),
        sorted(left_set | right_set),
    )
Practice

Implement set_relationships(left, right). Return sorted shared values, values only on the left, and the full union as a tuple of lists.

Public tests

  • Verify intersection difference union

Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor

Choose set or dict

Use a set for presence, deduplication, visited state, and algebra. Use a dictionary when each key must retain a count, original index, predecessor, or computed value. Use a boolean list when the key domain is small and dense; it may be faster and makes the bounded domain explicit.

Common Pitfalls

  • Using a mutable list as a member raises TypeError; choose an immutable semantic key.
  • Depending on set iteration order creates unstable output even if one run looks consistent.
  • Removing while iterating the same set can raise a runtime error.
  • Building set(values) too early loses duplicate positions and encounter order.
  • Claiming worst-case O(1) ignores collision behavior and the cost of hashing long keys.

Explain It in an Interview

State exactly what membership means and why no payload is needed. Define when a value enters the set and whether input order must survive. Give expected O(1) operations and O(n) space, while noting that hashing a compound key includes the work needed to hash its contents.

Track Previously Seen Values(opens in a new tab) isolates the prefix invariant. Design HashSet(opens in a new tab) then asks you to implement collision-safe membership without relying on the built-in set.

Python Version Note

Python 3.11+

The examples use standard Python containers and syntax available in the supported browser runtime; Hash Set itself is taught as an interview abstraction.

Verify in Python docs(opens in a new tab)

Complexity & Invariants

Interview bounds depend on the stated representation, input model, and real Python operations.

OperationAverageWorstInterview note
Core Hash Set workflowO(n) expectedO(n) expectedMembership questions about everything processed so far usually call for a hash set rather than repeated prefix scans. Before processing index i, seen contains exactly the distinct values from indices smaller than i.

Space

O(n) for the demonstrated Hash Set workflow.

Assumptions

  • Hash operations are average constant time but can degrade under collision-heavy inputs; storage grows with entries.
  • The bound counts the operations in Track Previously Seen Values and does not hide Python slicing, sorting, or copying.

Invariants Worth Saying Aloud

  1. State the precise Hash Set invariant before coding and preserve it after every update, traversal step, or recursive return.
  2. Membership questions about everything processed so far usually call for a hash set rather than repeated prefix scans. This remains true after every accepted operation.
  3. Before processing index i, seen contains exactly the distinct values from indices smaller than i. This remains true after every accepted operation.

When To Use Or Avoid Hash Set

Use It When

  • Use Hash Set when its representation directly supports the prompt's repeated query or update.
  • Use it when the invariant can be stated before coding and preserved after every operation.

Choose Another Tool When

  • Avoid it when a simpler Python sequence or mapping communicates the same contract with less state.
  • Avoid it when building the structure costs more time or space than the number of required queries can justify.

Common Pitfalls

These are the mistakes most likely to survive a happy-path example and fail a boundary case.

Leaving the core transition unfinished

Placeholder code cannot preserve the Hash Set invariant or satisfy the public contract.

Prevent it: Implement the smallest complete transition and run the public tests before adding optimizations.

Avoid

def track_seen_values(values):
    pass

Use instead

def track_seen_values(values):
    seen = set()
    result = []
    for value in values:
        result.append(value in seen)
        seen.add(value)
    return result

Breaking the central invariant

Adds each value before testing membership, so even first occurrences are reported as repeats.

Prevent it: Keep this invariant visible while editing: State the precise Hash Set invariant before coding and preserve it after every update, traversal step, or recursive return.

Avoid

def track_seen_values(values):
    seen = set()
    result = []
    for value in values:
        seen.add(value)
        result.append(value in seen)
    return result

Use instead

def track_seen_values(values):
    seen = set()
    result = []
    for value in values:
        result.append(value in seen)
        seen.add(value)
    return result

Hiding Python work inside the loop

Handle empty state, duplicate values, aliasing, and serialization boundaries explicitly in tests.

Prevent it: Account for every slice, copy, sort, membership test, and container mutation before claiming O(n) expected.

Avoid

def track_seen_values(values):
    seen = set()
    result = []
    for value in values:
        seen.add(value)
        result.append(value in seen)
    return result

Use instead

def track_seen_values(values):
    seen = set()
    result = []
    for value in values:
        result.append(value in seen)
        seen.add(value)
    return result

Reviewed References

Official Python documentation supports language behavior. Canonical problem pages provide additional practice context.