Quick Overview

Coding problem: replay an n-by-n tic-tac-toe game from a list of moves and report after every move whether the player who just moved has filled a row, a column or either diagonal. It tests efficient win detection on large boards and careful handling of diagonal and anti-diagonal cells.

Report the winner after each move on an n-by-n tic-tac-toe board

Company: ByteDance

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Onsite

Two players play a generalized game of tic-tac-toe on an `n × n` board. The players are numbered 1 and 2, and each move places the moving player's mark on an empty cell. A player wins as soon as their marks fill an entire row, an entire column, the main diagonal or the anti-diagonal. Given `n` and the moves in the order they are played, return the result of the game immediately after each move. ### Function Signature ```python def tic_tac_toe_results(n: int, moves: list[list[int]]) -> list[int]: ``` `moves[i] = [row, col, player]` means that player `player` places a mark on the cell in row `row` and column `col`, both 0-indexed. ### Rules - The main diagonal is the cells `(i, i)` and the anti-diagonal is the cells `(i, n - 1 - i)`, for `0 <= i < n`. - The result after a move is the number of the player who has won, or 0 if nobody has won yet. Only the player who just moved can have just won. - Moves are applied in the given order, and each move targets a cell that is still empty. The input does not have to alternate between the players; do not check whose turn it is. - The game ends at the first winning move, and no moves follow it, so only the last result can be nonzero. - Return one result per move, in move order. ### Constraints - `2 <= n <= 100` - `1 <= len(moves) <= n * n` - `0 <= row, col < n`, and no two moves use the same cell - `player` is 1 or 2 - No move comes after a winning move ### Examples **Example 1** ```text Input: n = 3, moves = [[1, 1, 1], [0, 0, 2], [0, 2, 1], [2, 0, 2], [1, 0, 1], [2, 2, 2], [1, 2, 1]] Output: [0, 0, 0, 0, 0, 0, 1] ``` The last move gives player 1 the cells `(1, 0)`, `(1, 1)` and `(1, 2)`, the whole middle row. Before it, no row, column or diagonal belonged entirely to one player. **Example 2** ```text Input: n = 2, moves = [[0, 1, 2], [1, 1, 1], [1, 0, 2]] Output: [0, 0, 2] ``` Player 2 moves first and completes the anti-diagonal `(0, 1)`, `(1, 0)` on the third move. **Example 3** ```text Input: n = 4, moves = [[0, 0, 2], [0, 1, 1], [1, 1, 2], [0, 2, 1], [2, 2, 2]] Output: [0, 0, 0, 0, 0] ``` Player 2 holds three of the four cells of the main diagonal, which is not a win on a `4 × 4` board, so the game is still undecided after every move.

Overview: Coding problem: replay an n-by-n tic-tac-toe game from a list of moves and report after every move whether the player who just moved has filled a row, a column or either diagonal. It tests efficient win detection on large boards and careful handling of diagonal and anti-diagonal cells.

Two players play a generalized game of tic-tac-toe on an `n × n` board. The players are numbered 1 and 2, and each move places the moving player's mark on an empty cell. A player wins as soon as their marks fill an entire row, an entire column, the main diagonal or the anti-diagonal. Given `n` and the list `moves` in the order the moves are played, return the result of the game immediately after each move. `moves[i] = [row, col, player]` means that player `player` places a mark on the cell in row `row` and column `col`, both 0-indexed. ### Rules - The main diagonal is the cells `(i, i)` and the anti-diagonal is the cells `(i, n - 1 - i)`, for `0 <= i < n`. - The result after a move is the number of the player who has won, or `0` if nobody has won yet. Only the player who just moved can have just won. - Moves are applied in the given order, and each move targets a cell that is still empty. The input does not have to alternate between the players; do not check whose turn it is. - The game ends at the first winning move, and no moves follow it, so only the last result can be nonzero. - Return a list with one result per move, in move order, so its length equals `len(moves)`. Every result is `0`, `1` or `2`. ### Constraints - `2 <= n <= 100` - `1 <= len(moves) <= n * n` - `0 <= row, col < n`, and no two moves use the same cell - `player` is 1 or 2 - No move comes after a winning move No input or output value can exceed 2^31 - 1, so 32-bit integers suffice in every language. ### Example 1 ```text Input: n = 3, moves = [[1, 1, 1], [0, 0, 2], [0, 2, 1], [2, 0, 2], [1, 0, 1], [2, 2, 2], [1, 2, 1]] Output: [0, 0, 0, 0, 0, 0, 1] ``` The last move gives player 1 the cells `(1, 0)`, `(1, 1)` and `(1, 2)`, the whole middle row. Before it, no row, column or diagonal belonged entirely to one player. ### Example 2 ```text Input: n = 2, moves = [[0, 1, 2], [1, 1, 1], [1, 0, 2]] Output: [0, 0, 2] ``` Player 2 moves first and completes the anti-diagonal `(0, 1)`, `(1, 0)` on the third move.

Constraints

  • 2 <= n <= 100
  • 1 <= len(moves) <= n * n
  • moves[i] = [row, col, player] with 0 <= row, col < n
  • No two moves use the same cell
  • player is 1 or 2
  • No move comes after a winning move

Examples

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

Expected Output: [0, 0, 0, 0, 0, 0, 1]

Explanation: Source Example 1: the seventh move completes row 1 for player 1; every earlier line is mixed or incomplete.

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

Expected Output: [0, 0, 2]

Explanation: Source Example 2: player 2 moves first and completes the anti-diagonal (0, 1), (1, 0) of the 2 x 2 board on the third move.

Hints

  1. Only the player who just moved can have just won, and only through a row, column or diagonal that contains the cell they just marked.
  2. A line is a win only when all n of its cells hold the same player's mark; a full line shared by both players is not a win.
  3. Read the player from each move itself: the input does not have to alternate between the players.

Loading coding console...

Show the approach

Approach

Keep, for each player p, a count of p's marks in every row, every column, the main diagonal and the anti-diagonal (rows[p * n + r], cols[p * n + c], diag[p], anti[p]). Invariant: after k moves, each count equals the number of cells of that line holding p's mark. Because every move targets a distinct empty cell and a line has exactly n cells, p owns a whole line exactly when p's count on it equals n; a line shared by both players never reaches n for either player, so mixed full lines are correctly not wins. A move at (row, col) by player p changes only the counts of p's row, p's column and the diagonals the cell lies on: the main diagonal when row == col and the anti-diagonal when row + col == n - 1. The center of an odd board lies on both, so both checks are independent (never else-if). The result after the move is p if any updated count is now n, otherwise 0; by the input guarantees only the last result can be nonzero. Edge cases: a single move never wins because n >= 2; the players need not alternate, so the player is always read from the move itself; a full board whose every line is mixed yields all zeros.

Time complexity:
O(n + m), where m = len(moves)
Space complexity:
O(n) auxiliary, O(n + m) including the returned list