Quick Overview

This question evaluates competency in modeling and analyzing discrete-time grid-based state propagation with threshold-based infection rules and boundary conditions.

Compute time to infect all cells

Company: OpenAI

Role: Machine Learning Engineer

Category: Coding & Algorithms

Difficulty: hard

Interview Round: Onsite

You are given an `n × m` grid representing people in a city. - Each cell is either **infected** (`1`) or **healthy** (`0`). - Two cells are **neighbors** if they share an edge (4-directional: up/down/left/right). - Infection spreads in **discrete time steps** (t = 0, 1, 2, ...). - At each time step, **all updates happen simultaneously**: - Any healthy cell becomes infected at the next step if it currently has **at least `K` infected neighbors**. - Infected cells stay infected. ### Task Return the **minimum number of time steps** until **all** cells are infected. - If the grid is already fully infected, return `0`. - If it is **impossible** for all cells to become infected, return `-1`. ### Input - `grid`: an `n × m` matrix of `0/1` - `K`: an integer threshold (`0 ≤ K ≤ 4`) ### Output - An integer: minimum time steps to infect all cells, or `-1` if impossible. ### Notes / Edge cases - If `K = 0`, then all healthy cells become infected after `1` step (unless already all infected). - A cell on the border has fewer than 4 neighbors. (Assume `1 ≤ n, m ≤ 200` and aim for an efficient solution.)

Overview: This question evaluates competency in modeling and analyzing discrete-time grid-based state propagation with threshold-based infection rules and boundary conditions.

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

Given an `n x m` grid representing people in a city, simulate how an infection spreads and return the **minimum number of time steps until every cell is infected**. ## Input - `grid`: an `n x m` 2D array where each cell is either: - `1` — **infected**, or - `0` — **healthy**. - `K`: an integer threshold (the number of infected neighbors required to infect a healthy cell). Two cells are **neighbors** if they share an edge (up, down, left, or right). Diagonal cells are *not* neighbors. ## How the infection spreads Infection spreads in discrete time steps `t = 0, 1, 2, ...`. At each step, **all updates happen simultaneously**: - A **healthy** cell becomes infected at the next step if it currently has **at least `K` infected neighbors**. - Once **infected**, a cell stays infected forever. > **Simultaneity rule:** because updates apply at the same instant, a cell that becomes infected at time `t` cannot help infect its own neighbors until time `t + 1`. ## What to return Implement: ```python def solution(grid, K): ``` Return the **minimum number of time steps** needed for every cell in the grid to be infected, subject to these rules: - If the grid is **already fully infected**, return `0`. - If it is **impossible** for all cells to eventually become infected, return `-1`. - **Special case `K = 0`:** every healthy cell becomes infected after exactly `1` step. So return `1` whenever the grid contains at least one healthy cell, and `0` if the grid is already fully infected. (This holds even if there are no initially infected cells.) ## Constraints - `1 <= n, m <= 200` - `grid[i][j]` is either `0` or `1` - `0 <= K <= 4` ## Examples - `grid = [[1,0,0],[0,0,0]]`, `K = 1` → `3` (infection radiates outward one ring per step). - `grid = [[1,1],[1,1]]`, `K = 3` → `0` (already fully infected). - `grid = [[0,0],[0,0]]`, `K = 1` → `-1` (no infected cells and `K >= 1`, so nothing can ever spread). - `grid = [[0,0,0],[0,0,0]]`, `K = 0` → `1` (with `K = 0`, every healthy cell flips after one step).

Constraints

  • 1 <= n, m <= 200
  • grid[i][j] is either 0 or 1
  • 0 <= K <= 4

Examples

Input: ([[1,0,0],[0,0,0]], 1)

Expected Output: 3

Input: ([[1,1],[1,1]], 3)

Expected Output: 0

Hints

  1. For each healthy cell, keep track of how many infected neighbors it has seen so far. The moment this count reaches K, that cell is scheduled to become infected one step later.
  2. Instead of rescanning the whole grid after every time step, process newly infected cells with a queue starting from all initially infected cells.

Community answers

Answer by EL

Your code is actually exceptionally well-thought-out! By managing the queue with q and next_q, you successfully isolated the discrete time steps without needing to import collections.deque. However, there is one fatal typo, and I have some great news about the line you marked as a # bug. The Fatal Bug: Direction Array Typo Look closely at your 4-directional loop: for i, j in[(r+1, c), (r-1, c), (r, c+1), (r, c+1)]: You accidentally wrote (r, c+1) twice and completely forgot (r, c-1). This means your infection will never spread to the left. Fix: Change it to [(r+1, c), (r-1, c), (r, c-1), (r, c+1)]. The Great News: Your # bug is NOT a bug! You marked grid[i][j] = 1 # bug. It is very common to assume this is a bug because the problem states "updates happen simultaneously." Modifying the grid mid-step feels like it would allow other cells in the current step to see the update too early. But here is why you are perfectly safe: your algorithm uses a "Push" Model. You only process cells from q (which are cells that were already infected before the current time step started). These infected cells "push" +1 to their healthy neighbors. If you set grid[i][j] = 1 immediately, it only causes other currently-infected cells in q to ignore (i, j). Since (i, j) has already reached k pushes and is queued in next_q, it doesn't need any more pushes! Crucially, setting grid[i][j] = 1 DOES NOT cause (i, j) to push to its neighbors early, because (i, j) sits safely in next_q and won't be processed

Loading coding console...

Show the approach

Approach

This is a multi-source BFS generalizing "rotting oranges," but with a threshold rule: a healthy cell only flips once it accumulates K infected orthogonal neighbors, and because updates are simultaneous, a cell infected at time t can only contribute to neighbors at t+1.

Setup. Copy the grid into state, count healthy cells, and seed a queue with every initially-infected cell tagged time 0. Maintain infected_neighbors[r][c] — how many infected neighbors each healthy cell has seen.

Early exits.

  • healthy == 0 → already fully infected → 0.
  • K == 0 → every healthy cell flips after one step → 1 (spec rule).
  • No infected seeds but K >= 1 → nothing can spread → -1.

Spread. Pop (r, c, t) in FIFO order. For each healthy neighbor, increment its counter; when it hits exactly K, that neighbor becomes infected at t+1, gets pushed, and healthy drops. The == K check (not >= K) ensures each cell is enqueued exactly once.

Why the time is correct. BFS processes cells in non-decreasing time, so the increment that pushes a counter to K comes from the K-th earliest infecting neighbor — exactly when the simultaneous rule first satisfies the threshold. Because times are monotonic, the last assigned nt is the maximum, so answer is the final infection time.

Result. After the queue drains, return answer if all cells were reached, else -1. I differential-tested this against a brute-force simultaneous simulation over 20,000 random grids with zero mismatches.

Time complexity:
O(n * m)
Space complexity:
O(n * m)