Rectangle grid with IDs: coverage counts, replace and delete, O(1) queries, batch undo

Read the full interview experience this question came from →

Quick Overview

Build a class that places rectangles with IDs on a grid and reports how many rectangles cover a cell. Requirements grow over five parts: replacement and deletion by ID, constant-time queries with updates proportional to area, undo of the latest change, and removal of every rectangle at a point that a single undo restores.

Rectangle grid with IDs: coverage counts, replace and delete, O(1) queries, batch undo

Company: OpenAI

Role: Machine Learning Engineer

Category: Software Engineering Fundamentals

Difficulty: hard

Interview Round: Technical Screen

Implement a class that maintains a two-dimensional grid of cells onto which rectangles are placed, each rectangle with its own ID. The requirements arrive in five parts, each building on the code from the previous one. Expect a fair amount of code; having a clear plan for undo before Part 4 makes the later parts much smoother. Assume, unless the interviewer says otherwise, that the grid has `width` columns and `height` rows, that cell `(x, y)` satisfies `0 <= x < width` and `0 <= y < height`, and that a rectangle is given by two opposite corner cells `(x1, y1)` and `(x2, y2)` with `x1 <= x2` and `y1 <= y2`, covering every cell between them, corners included. Rectangles may overlap. ### Clarifying Questions - Is a rectangle that extends past the grid rejected, clipped, or ruled out by contract? - Are the corners always given in order, or must the class normalize them? - How should a failed operation, such as removing an unknown ID, be reported: an exception, a return value, or silently? ### Part 1 — Add rectangles and count coverage Implement `add(rect_id, x1, y1, x2, y2)` and `query(x, y)`, which returns how many rectangles cover cell `(x, y)`. In this part every ID is new. ```hint Correct first Start with the representation that makes both operations obviously correct; the later parts will say which operation has to be fast. ``` #### What This Part Should Cover - Inclusive boundary handling and validation of the input - A clear data representation, with the cost of each operation - A few hand-checked cases with overlapping rectangles ### Part 2 — Replace and delete by ID Adding a rectangle with an ID that already exists replaces that ID's old rectangle with the new one. Also implement `remove(rect_id)`, which deletes the rectangle with that ID. ```hint Replacing safely Think about what has to happen to the old rectangle before the new one takes effect, and what should remain if the new rectangle turns out to be invalid. ``` #### Clarifying Questions for this Part - If the replacement rectangle is invalid, should the old rectangle stay in place? #### What This Part Should Cover - An ID-to-rectangle mapping and the exact replacement semantics - Behavior for unknown IDs and invalid replacements - How the cost of each operation changes, if at all ### Part 3 — Constant-time queries Change the implementation so that `query` runs in O(1), while `add` and `remove`, including replacement, take time proportional to the area of the rectangles they touch. ```hint Shift the work Decide what per-cell information could be kept up to date on every write so that a query becomes a single lookup. ``` #### What This Part Should Cover - The per-cell state maintained on every write, kept consistent with the ID map - The exact cost of add, remove and replace, and the memory used - When this trade-off is the wrong one, for example for a very large grid ### Part 4 — Undo Implement `undo()`, which reverts the most recent successful modification. Undoing a replacement must restore the previous rectangle for that ID, and calling `undo()` repeatedly keeps walking back through earlier modifications. ```hint Remember the past For each successful change, record just enough to put every affected ID back exactly the way it was. ``` #### Clarifying Questions for this Part - Do failed operations and queries leave anything to undo? - What should `undo()` do when there is nothing left to undo? #### What This Part Should Cover - A history record that handles add, replace and remove uniformly - Undo that restores both the ID map and the per-cell state - The cost of undo and the memory the history uses ### Part 5 — Remove everything at a point Implement `remove_at(x, y)`, which deletes every rectangle covering cell `(x, y)`. A single `undo()` must restore that whole batch. ```hint One change, many rectangles Let a single history record describe several IDs at once. ``` #### Clarifying Questions for this Part - If no rectangle covers the cell, does the call count as a modification that `undo()` would consume? #### What This Part Should Cover - Finding the covering rectangles, and its cost - A batch history entry that one undo reverses completely - Whether to keep extra per-cell data to make this operation faster ### What a Strong Answer Covers - Incremental code that keeps the ID map, the per-cell counts and the history consistent after every operation - Correct inclusive boundaries and validation of rectangles and IDs - Stated complexity for every operation in every version, meeting the Part 3 bounds - One history format that handles add, replace, delete and batch delete - Tests for tricky sequences: replace then undo, undo across a batch, undo with an empty history ### Follow-up Questions - Add `redo()`. What happens to it when a new modification arrives after an undo? - The grid is a billion cells on each side and rectangles can be enormous. What can you offer for `add` and `query` now? - How would you cap the memory used by the undo history? - Several threads call these methods at once. What must be atomic?

Overview: Build a class that places rectangles with IDs on a grid and reports how many rectangles cover a cell. Requirements grow over five parts: replacement and deletion by ID, constant-time queries with updates proportional to area, undo of the latest change, and removal of every rectangle at a point that a single undo restores.

Read the full OpenAI Machine Learning Engineer interview experience this question came from

OpenAI logo
OpenAI
Oct 29, 2026
hardMachine Learning EngineerTechnical ScreenSoftware Engineering Fundamentals
1
0

Implement a class that maintains a two-dimensional grid of cells onto which rectangles are placed, each rectangle with its own ID. The requirements arrive in five parts, each building on the code from the previous one. Expect a fair amount of code; having a clear plan for undo before Part 4 makes the later parts much smoother.

Assume, unless the interviewer says otherwise, that the grid has width columns and height rows, that cell (x, y) satisfies 0 <= x < width and 0 <= y < height, and that a rectangle is given by two opposite corner cells (x1, y1) and (x2, y2) with x1 <= x2 and y1 <= y2, covering every cell between them, corners included. Rectangles may overlap.

Clarifying Questions Guidance

  • Is a rectangle that extends past the grid rejected, clipped, or ruled out by contract?
  • Are the corners always given in order, or must the class normalize them?
  • How should a failed operation, such as removing an unknown ID, be reported: an exception, a return value, or silently?

Part 1 — Add rectangles and count coverage

Implement add(rect_id, x1, y1, x2, y2) and query(x, y), which returns how many rectangles cover cell (x, y). In this part every ID is new.

What This Part Should Cover Guidance

  • Inclusive boundary handling and validation of the input
  • A clear data representation, with the cost of each operation
  • A few hand-checked cases with overlapping rectangles

Part 2 — Replace and delete by ID

Adding a rectangle with an ID that already exists replaces that ID's old rectangle with the new one. Also implement remove(rect_id), which deletes the rectangle with that ID.

Clarifying Questions for this Part Guidance

  • If the replacement rectangle is invalid, should the old rectangle stay in place?

What This Part Should Cover Guidance

  • An ID-to-rectangle mapping and the exact replacement semantics
  • Behavior for unknown IDs and invalid replacements
  • How the cost of each operation changes, if at all

Part 3 — Constant-time queries

Change the implementation so that query runs in O(1), while add and remove, including replacement, take time proportional to the area of the rectangles they touch.

What This Part Should Cover Guidance

  • The per-cell state maintained on every write, kept consistent with the ID map
  • The exact cost of add, remove and replace, and the memory used
  • When this trade-off is the wrong one, for example for a very large grid

Part 4 — Undo

Implement undo(), which reverts the most recent successful modification. Undoing a replacement must restore the previous rectangle for that ID, and calling undo() repeatedly keeps walking back through earlier modifications.

Clarifying Questions for this Part Guidance

  • Do failed operations and queries leave anything to undo?
  • What should undo() do when there is nothing left to undo?

What This Part Should Cover Guidance

  • A history record that handles add, replace and remove uniformly
  • Undo that restores both the ID map and the per-cell state
  • The cost of undo and the memory the history uses

Part 5 — Remove everything at a point

Implement remove_at(x, y), which deletes every rectangle covering cell (x, y). A single undo() must restore that whole batch.

Clarifying Questions for this Part Guidance

  • If no rectangle covers the cell, does the call count as a modification that undo() would consume?

What This Part Should Cover Guidance

  • Finding the covering rectangles, and its cost
  • A batch history entry that one undo reverses completely
  • Whether to keep extra per-cell data to make this operation faster

What a Strong Answer Covers Guidance

  • Incremental code that keeps the ID map, the per-cell counts and the history consistent after every operation
  • Correct inclusive boundaries and validation of rectangles and IDs
  • Stated complexity for every operation in every version, meeting the Part 3 bounds
  • One history format that handles add, replace, delete and batch delete
  • Tests for tricky sequences: replace then undo, undo across a batch, undo with an empty history

Follow-up Questions Guidance

  • Add redo() . What happens to it when a new modification arrives after an undo?
  • The grid is a billion cells on each side and rectangles can be enormous. What can you offer for add and query now?
  • How would you cap the memory used by the undo history?
  • Several threads call these methods at once. What must be atomic?