Design adjustable ID allocator
PinterestSoftware Engineer · OnsiteLast updated
A Pinterest software-engineer onsite coding problem: design an adjustable ID allocator over a fixed [0, 999] ID space with named, contiguous, non-overlapping bucket ranges. It covers initial allocation (packing from desired sizes and validating/normalizing proposed ranges), a resize operation that grows or shrinks a bucket by consuming adjacent free space and then minimally shifting or borrowing from neighbors under a deterministic policy, plus complexity analysis, boundary-case testing, and concurrency handling.
Question
You manage a fixed global integer ID space [0, 999] (1000 IDs total) and a set of named buckets. Each bucket has a unique name and occupies a contiguous, inclusive range of IDs [start, end]. Ranges must always stay non-overlapping, in bounds, and (depending on the variant) in a fixed order; any IDs not owned by a bucket are considered free. Design the data structures and APIs, then implement the following operations.
- Initial allocation / assignment. Implement an operation that takes the initial bucket specifications and assigns each bucket a valid contiguous range. Support both common framings:
- Given a list of
(name, desired_size)in a fixed order, pack the buckets contiguously from low IDs to high IDs, preserving the given order, and return[(name, start_id, end_id), ...]. Fail with a clear error if the sum of desired sizes exceeds 1000 (capacity). - Given a list of buckets that already carry proposed
[start, end]ranges, validate and normalize them so they are within[0, 999], non-overlapping, and returned sorted by start. Leave any unassigned IDs free (allow gaps between buckets).
- Resize a bucket. Implement
resize(name, new_desired_size)(orresize(buckets, name, desired_size)) that grows or shrinks the named bucket so it owns exactlynew_desired_sizeIDs, while keeping every range contiguous, disjoint, in bounds, and (where required) in order:
- When growing, prefer consuming immediately adjacent free space first.
- If adjacent free space is insufficient, recover space by minimally shifting only the neighboring ranges, or by borrowing from neighboring buckets using a deterministic policy (e.g., take from the nearest bucket that has the largest surplus). Shifts/borrows must be the minimum needed to satisfy the request.
- When shrinking, return the freed IDs to the free pool (or to neighbors per policy).
- If the request cannot be satisfied within total capacity, return a clear, well-defined error and leave the layout unchanged.
- Analysis and follow-ups.
- State the data structures you chose and the time/space complexity of each operation.
- Describe how you would test boundary cases: empty bucket list, a zero-size bucket, full utilization (sum == 1000), expansions that would overflow capacity, resizing the first/last bucket, and resizing a non-existent name.
- Discuss how you would handle concurrent or conflicting
resizecalls (e.g., locking, optimistic versioning, or a deterministic ordering/serialization of requests).
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.