PrepStack · Markdown HTML

Same-direction / read-write pointers

Pointers and sliding window · HTML

Formal shape

Before each iteration, [0,write) is the correct output derived from items before read. After inspecting a[read], optionally write it at a[write] and advance write.

Recognition signals

False friends

SignalWhy it is different
Contiguous window constraintIf left is a window boundary that repeatedly shrinks, use sliding-window semantics.
Arbitrary reordering allowedSwapping with the tail may use fewer writes; stable read-write is not always necessary.

Core invariant

After processing a[0:read], a[0:write] is exactly its correct stable filtered output, with write no farther than read+1.

State, transition, and processing order

ItemDefinition
Stateread, write, current value, and the small summary required to decide retention.
Transitionread advances every round; when the item is retained, store it at a[write] and increment write.
Frontier / order[0,write) is final output, [write,read) may be overwritten, and [read,n) remains unread input.

Python skeleton

def stable_filter(values, keep):
    write = 0
    for read, value in enumerate(values):
        if keep(value):
            values[write] = value
            write += 1
    return write  # valid output is values[:write]

Correctness sketch

  1. The empty prefix is initially correct.
  2. Discarding leaves the correct output unchanged; retaining appends exactly the next stable item at write.
  3. Induction through read=n gives all and only retained items in the prefix, with write as its length.

Complexity

TimeSpaceParameters
O(n)O(1)n is input length; each item is read once and written at most once.

Edge cases

Error patterns

PatternWhy it fails / fix
Returning the whole arrayThe tail contains unspecified old values; only [:write] is valid.
Incrementing write unconditionallyThat preserves holes for items meant to be removed.
Reading overwritten storageMaintain write behind read and base summaries on the valid prefix.

Selection and exclusion rules

RelationTemplateBoundary

Original micro-example

PartDetail
Resultwrite=3 and the valid prefix is [4,6,8].
SetupRetain even values in [4,1,6,3,8] in place.
Traceread scans; 4 writes at 0, 6 at 1, and 8 at 2.

Recall prompts

My notes