PrepStack · Markdown HTML

Data-structure design / operation invariant

Geometry, sweep, simulation, and parsing · HTML

Formal shape

Given operations and bounds, list each operation's reads and writes, choose complementary structures, and define synchronized updates for every duplicate representation.

Recognition signals

False friends

SignalWhy it is different
One offline computationIf every operation is known in advance, sorting or batching may be simpler than an online structure.
Excess duplicated stateEvery derived copy adds a synchronization obligation and a path to ghost entries.

Core invariant

Every logical element has consistent representations across indices; primary storage owns truth and auxiliary indices only accelerate access.

State, transition, and processing order

ItemDefinition
StateChoose arrays, hashes, heaps, or linked lists from operation needs; the example IndexedSet pairs items with reverse positions.
TransitionEach public operation checks preconditions and updates every structure in an order that preserves needed references, restoring the invariant before return.
Frontier / orderThere is no traversal frontier; each API-call boundary is a transaction boundary at which the full invariant must hold.

Python skeleton

class IndexedSet:
    def __init__(self):
        self.items = []
        self.pos = {}
    def add(self, value):
        if value in self.pos: return False
        self.pos[value] = len(self.items)
        self.items.append(value)
        return True
    def remove(self, value):
        if value not in self.pos: return False
        i = self.pos.pop(value)
        last = self.items.pop()
        if i < len(self.items):
            self.items[i] = last
            self.pos[last] = i
        return True
    def contains(self, value):
        return value in self.pos
    def at(self, index):
        return self.items[index]

Correctness sketch

  1. Initially both array and map are empty, so the bidirectional correspondence holds.
  2. add appends a new value and records exactly that position.
  3. remove fills the hole with the last value and updates the moved value's position.
  4. All other positions remain unchanged, restoring the invariant before each return.

Complexity

TimeSpaceParameters
Amortized O(1) add/remove/contains and O(1) atO(n)n current elements; bounds rely on amortized hashing

Edge cases

Error patterns

PatternWhy it fails / fix
Not updating the moved indexThe last value keeps a stale position after hole filling.
Popping before preserving needed dataMutation order must retain every value needed later.
Testing outputs but not invariantsAfter random operations, verify both directions between pos and items.

Selection and exclusion rules

RelationTemplateBoundary
ordered compositionLinked-list pointer rewiringO(1) deletion must preserve access order
composite structureTwo heaps for streaming medianAn online structure maintains lower and upper halves

Original micro-example

PartDetail
Resultitems may become [a,c], with positions a→0 and c→1.
ScenarioAdd a, b, c to an IndexedSet, then remove b.
WalkthroughMove final item c into b's hole and change c's reverse index from 2 to 1.

Recall prompts

My notes