◀ THE GRIND — BINARY SEARCH

Time Based Key Value Store

MEDIUM✓ CHIP-TIMEDLC #981 — FULL STATEMENT ↗

The drill: A key-value store where writes carry a timestamp and reads ask for whatever value was current at some earlier moment — set stores a stamped write, get answers what was true at or before this time, or the empty string if nothing existed yet.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

This drill builds a key-value store where every write is stamped with a timestamp instead of simply overwriting whatever was there before — a key can carry many values across its history, one per moment it was set.

Reading a key doesn't ask for its current value; it asks what the value was at or before some specified timestamp, and the store has to reconstruct that answer from everything it's recorded so far.

If a read's timestamp lands before the key was ever written, the honest answer is an empty string — there's no value yet to report at that point in time.

Writes for any given key always arrive in increasing timestamp order on this course, so each key's history is naturally sorted the moment it's queried.

EX 01
TimeMap()
set("alpha", "one", 5)
get("alpha", 5) → "one"
EXACT TIMESTAMP MATCH
EX 02
TimeMap()
get("ghost", 10) → ""
GET BEFORE ANY SET AT THAT KEY
EX 03
TimeMap()
set("k", "v1", 10)
get("k", 5) → ""
QUERY LANDS BEFORE THE FIRST WRITE
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Every write for a key lands with a timestamp; a read isn't asking for THE value, it's asking which stamped write was the most recent one at or before a given moment. Replaying the full history answers that, but slowly.

HINT 2 THE STRUCTURE

Writes for a key always arrive with strictly increasing timestamps, so each key's history is already sorted by the time it gets queried. Sorted history plus a “closest at or before” question is a binary-search shape.

HINT 3 ONE STEP FROM THE ANSWER

Keep each key's timestamps (and matching values) in a growing sorted list; binary-search for the rightmost timestamp not exceeding the query and read the value beside it, or the empty string if the query lands before the first write.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE STAMPED LEDGERPATTERN · BINARY SEARCH THE LEDGERset(c,v1,1) · set(c,v2,4) · set(c,v3,9) · get(c,1) · get(c,5) · get(c,9)
new
set c,v1@1
set c,v2@4
set c,v3@9
get c@1
get c@5
get c@9
STORE — KEY → (TIMESTAMPS, VALUES)
— empty —
STEP 1

TimeMap stores stamped writes per key, then binary-searches each key's sorted timestamps for what was true at or before a moment.

STEP 1 / 9 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/time-based-key-value-store.pyRACE PACE
LANG ▸
PACE ▸
class TimeMap:
    def __init__(self):
        self.times: Dict[str, List[int]] = {}
        self.vals: Dict[str, List[str]] = {}

    def set(self, key: str, value: str, timestamp: int) -> None:
        self.times.setdefault(key, []).append(timestamp)
        self.vals.setdefault(key, []).append(value)

    def get(self, key: str, timestamp: int) -> str:
        stamps = self.times.get(key)
        if not stamps:
            return ""
        i = bisect.bisect_right(stamps, timestamp) - 1
        return self.vals[key][i] if i >= 0 else ""
TIME O(LOG N) GET, O(1) SETSPACE O(N)PYTHON · RACE PACE · 15 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED