AO
Back

Design a Parking Lot (OOD): Park, Unpark, Spot Types

Also reported as Parking Lot OOD · Parking Lot Design

CodingOnsiteLast reported October 2026Medium Frequency

Problem Overview

The round: a frequently reported Uber object-oriented design question (eight reports here), in phone screens, onsite coding rounds and one AI-assisted coding round. The reported core: a parking lot with park, unpark and checkCar, where motorcycle spots take only motorcycles and regular spots take both motorcycles and cars. Another report names the operations check-in and check-out; another calls it a parking building. In one screening round the candidate first designed the high-level structure with black-box components, then was asked for fully runnable code, with the focus on data structure choice, code quality and performance. One candidate who had not prepared it did not finish the code. Two graded parts here: one lot, then a multi-level building that stays fast at scale.

Part 1 — park, unpark, check_car, with spot types

class ParkingLot:
    def __init__(self, spots: list[str]): ...                     # spots[i] is "motorcycle" or "car"
    def park(self, plate: str, vehicle: str) -> int | None: ...   # vehicle is "motorcycle" or "car"
    def unpark(self, plate: str) -> int | None: ...
    def check_car(self, spot: int) -> str | None: ...
  • A "motorcycle" spot takes only motorcycles. A "car" spot takes cars and motorcycles.
  • park returns the spot index it used. A car takes the lowest-numbered free car spot. A motorcycle takes the lowest-numbered free motorcycle spot, and only if there is none, the lowest-numbered free car spot. If no allowed spot is free, return None.
  • unpark frees the vehicle's spot and returns its index, or None if that plate is not parked.
  • check_car returns the plate in a spot, or None if the spot is empty.
  • Raise ValueError for an unknown vehicle type, a plate that is already parked, or a spot index that does not exist.

Part 2 — a multi-level parking building, fast at scale

class ParkingBuilding:
    def __init__(self, levels: list[list[str]]): ...    # levels[l][i] is the type of spot i on level l
    def park(self, plate: str, vehicle: str) -> tuple[int, int] | None: ...
    def unpark(self, plate: str) -> tuple[int, int] | None: ...
    def check_car(self, level: int, spot: int) -> str | None: ...
  • Same rules as Part 1. Spots are identified by (level, index), and "lowest" means lowest level first, then lowest index. A motorcycle still takes any free motorcycle spot in the building before a car spot.
  • park and unpark must stay fast: the tests fill 200,000 spots and then run 100,000 departures and arrivals. Scanning for a free spot on every park is too slow.

Notes: the reports give the operations and the spot rule, not an interface. The class and method names, string vehicle types, spot numbering, "lowest free spot first", a motorcycle preferring a motorcycle spot, None for a full lot or an unknown plate, and the ValueError cases are ours. The reference also accepts check_in and check_out as names for park and unpark.

Follow-up Arc

Interviewers escalate through these phases. The order varies, but most candidates see at least one from each bucket.
Trade-off discussion · 2
Trade-off discussion

Now write fully runnable code, not just the skeleton.

Probes for: after the high-level class structure is defined

What data structures did you choose and why? How does this affect performance?

Probes for: after the initial implementation

Approach Trade-offs

Approaches actually attempted in reports — including ones that lost candidates time. Pick deliberately.
ApproachNotes
Linear scan for a free spotsimplest; O(S) per park, fine for a small lot.
A min-heap of free spots per spot typeO(log S) park and unpark; always hands out the lowest spot.
Per-level free countersO(levels) to find a level with space; enough when the exact spot does not matter.

What Reports Emphasize

Common mistakes: One candidate who had skipped this question while preparing and had not written OOD in a long time did not finish the code and failed.; Finishing is not the whole bar: one candidate wrote runnable code covering edge cases in every coding round, including this one, and was still rejected; they guessed their system design answer was the reason.

Interviewer hints: In one screening round the interviewer first asked only for a high-level structure with black-box components assumed, then asked for fully runnable code.; One report lists the round's focus as data structure choice, code quality and performance optimization.; In one onsite the question was a multi-story parking building.; One report names the operations check-in and check-out.

Edge cases to test: Motorcycle parking in a regular spot (allowed).; Regular car attempting to park in a motorcycle spot (rejected).; Parking lot is full: decide what park() returns or throws.; Unparking a plate that is not parked, or checking a spot that does not exist.; The same plate parked twice.; Multiple floors in a parking building: which spot is handed out first.

Practice

Write your own against 11 test cases, or read the worked solution — approach, complexity, and code that runs.

Prepping for Uber with friends?

Send them this page. It is free to read, no account needed.

More Uber Questions

Free preview

Every question in the Uber catalog gets this depth

What you just read — canonical solution, follow-up arc, what passing candidates actually did — exists for all 83 Uber questions, refreshed monthly from new candidate reports.

$59/mo — or $50/mo with the 3-month pass · cancel anytime
Uber · Coding · Reported 9× across candidate reports
Is this helpful?