Algorithms & Data Structuresmedium
Design Adjustable ID Allocator
Manage the fixed ID space [0, 999] — 1000 IDs — divided into named buckets that occupy contiguous, non-overlapping ranges. Implement two operations.
pack(requests)
Given (name, size) pairs in order, pack the buckets contiguously from ID 0 upward, preserving order, and return the layout as [name, start, end] triples.
- A zero-size bucket appears as [name, -1, -1] and does not advance the cursor.
- A negative size is an error.
- If the sizes sum past 1000, fail without allocating anything.
pack([["a", 100], ["b", 200], ["c", 50]]) => [["a", 0, 99], ["b", 100, 299], ["c", 300, 349]]
resize(buckets, name, newSize)
Given a packed layout, resize one bucket to own exactly newSize IDs:
- Feasibility first: if total − currentSize + newSize > 1000, fail without mutating the layout.
- The target keeps its start. Growth extends its end and shifts every later bucket right by the delta; shrinking pulls its end in and later buckets close the gap.
- An unknown name or a negative size is an error.
resize([["a", 0, 99], ["b", 100, 299], ["c", 300, 349]], "a", 150) => [["a", 0, 149], ["b", 150, 349], ["c", 350, 399]] resize([["a", 0, 99], ["b", 100, 299], ["c", 300, 349]], "a", 50) => [["a", 0, 49], ["b", 50, 249], ["c", 250, 299]]
Follow-ups
- A validation variant: accept caller-proposed [start, end] ranges (gaps allowed), reject overlap or out-of-bounds, return them sorted by start.
- How would concurrent resizes be kept safe — a lock over the whole space, or optimistic versioning with retry?