Quick Overview

Traverse an m x n matrix clockwise from the outside in, then handle a follow-up where some cells are blockers that the walk must turn away from. Tests careful simulation of direction changes, tracking of visited cells, and a precise rule for when the traversal stops.

Spiral Order of a Matrix With Blocker Cells That Force Clockwise Turns

Company: Temu

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

You are given an `m x n` matrix of integers. First, return all of its values in clockwise spiral order, from the outside in: start at the top-left cell, move right along the top row, down the right column, left along the bottom row, up the left column, and continue inward. Follow-up: the matrix may contain blockers. The traversal never enters a blocker; when it runs into one, it turns clockwise (a right turn), the same way it turns at the matrix edge or at a cell it has already visited. Return the values in the order they are visited. Without blockers the result is the ordinary spiral order, so a single function covers both questions. The report leaves open when the walk with blockers stops and what it does when one right turn is still blocked; the rules below settle both. ### Function Signature ```python def spiral_with_blockers(matrix: list[list[int]], blocked: list[list[int]]) -> list[int]: ``` Each entry of `blocked` is a blocker cell given as `[row, col]`. ### Rules - Row `0` is the top row and column `0` is the leftmost column. From `(r, c)`, right is `(r, c + 1)`, down is `(r + 1, c)`, left is `(r, c - 1)` and up is `(r - 1, c)`. A clockwise turn changes right to down, down to left, left to up, and up to right. - A cell is available when it is inside the matrix, is not a blocker, and has not been visited. - The walk begins on `(0, 0)` facing right; `(0, 0)` is visited first and its value is output first. - On each step, check the next cell in the current direction. If it is available, move there and output its value. Otherwise turn clockwise by 90 degrees and check again, trying at most four directions in all. The first direction with an available next cell becomes the current direction, and the walk moves one cell that way. - When no direction from the current cell leads to an available cell, the walk stops. Open cells that were never reached do not appear in the output. - Blockers never appear in the output. ### Constraints - `1 <= m, n <= 100`, where `m = len(matrix)` and `n = len(matrix[0])`; all rows have length `n`. - `-10^9 <= matrix[r][c] <= 10^9` - `0 <= len(blocked) <= m * n - 1` - All blocker cells are inside the matrix and distinct, and `[0, 0]` is never a blocker. ### Examples **Example 1** ```text Input: matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], blocked = [] Output: [1, 2, 3, 6, 9, 8, 7, 4, 5] ``` The ordinary spiral: the outer ring clockwise, then the center. **Example 2** ```text Input: matrix = [[1, 2, 3], [4, 5, 6]], blocked = [[0, 1]] Output: [1, 4, 5, 6, 3] ``` The blocker to the right of `(0, 0)` turns the walk down to `4`. At `(1, 0)` facing down, down and left are outside the matrix and up is visited, so after three clockwise turns the walk faces right and moves through `5` to `6`. At `(1, 2)` facing right, right and down are outside and left is visited, so it turns to face up and moves to `3`. At `(0, 2)` every direction is outside, visited or the blocker, so the walk stops. **Example 3** ```text Input: matrix = [[1, 2, 3, 4], [5, 6, 7, 8]], blocked = [[1, 3]] Output: [1, 2, 3, 4] ``` At `(0, 3)` facing right, right is outside, down is the blocker, left is visited and up is outside, so the walk stops before reaching the bottom row.

Overview: Traverse an m x n matrix clockwise from the outside in, then handle a follow-up where some cells are blockers that the walk must turn away from. Tests careful simulation of direction changes, tracking of visited cells, and a precise rule for when the traversal stops.

Read the full Temu Software Engineer interview experience this question came from

You are given an `m x n` integer matrix `matrix` and a list `blocked` of blocker cells, each given as `[row, col]`. Return the values of `matrix` in the order a clockwise spiral walk visits them. Without blockers the walk is the ordinary clockwise spiral, from the outside in: start at the top-left cell, move right along the top row, down the right column, left along the bottom row, up the left column, and continue inward. With blockers, the walk never enters a blocker; when it runs into one, it turns clockwise (a right turn), the same way it turns at the matrix edge or at a cell it has already visited. ### Rules - Row `0` is the top row and column `0` is the leftmost column. From `(r, c)`, right is `(r, c + 1)`, down is `(r + 1, c)`, left is `(r, c - 1)` and up is `(r - 1, c)`. A clockwise turn changes right to down, down to left, left to up, and up to right. - A cell is available when it is inside the matrix, is not a blocker, and has not been visited. - The walk begins on `(0, 0)` facing right; `(0, 0)` is visited first and its value is output first. - On each step, check the next cell in the current direction. If it is available, move there and output its value. Otherwise turn clockwise by 90 degrees and check again, trying at most four directions in all. The first direction with an available next cell becomes the current direction, and the walk moves one cell that way. - When no direction from the current cell leads to an available cell, the walk stops. Open cells that were never reached do not appear in the output. - Blockers never appear in the output. Return the visited values as a list, in visiting order. ### Example 1 ```text Input: matrix = [[1, 2, 3], [4, 5, 6]], blocked = [[0, 1]] Output: [1, 4, 5, 6, 3] ``` The blocker to the right of `(0, 0)` turns the walk down to `4`. At `(1, 0)` facing down, down and left are outside the matrix and up is visited, so after three clockwise turns the walk faces right and moves through `5` to `6`. At `(1, 2)` facing right, right and down are outside and left is visited, so it turns to face up and moves to `3`. At `(0, 2)` every direction is outside, visited or the blocker, so the walk stops. ### Example 2 ```text Input: matrix = [[1, 2, 3, 4], [5, 6, 7, 8]], blocked = [[1, 3]] Output: [1, 2, 3, 4] ``` At `(0, 3)` facing right, right is outside, down is the blocker, left is visited and up is outside, so the walk stops before reaching the bottom row. ### Constraints - `1 <= m, n <= 100`, where `m = len(matrix)` and `n = len(matrix[0])`; all rows have length `n`. - `-10^9 <= matrix[r][c] <= 10^9` - `0 <= len(blocked) <= m * n - 1` - All blocker cells are inside the matrix and distinct, and `[0, 0]` is never a blocker. No value can exceed `2^31 - 1` in magnitude, so 32-bit integers suffice; the output only copies matrix values.

Constraints

  • 1 <= m, n <= 100, where m = len(matrix) and n = len(matrix[0]); all rows have length n
  • -10^9 <= matrix[r][c] <= 10^9
  • 0 <= len(blocked) <= m * n - 1
  • All blocker cells are inside the matrix and distinct, and [0, 0] is never a blocker

Examples

Input: ([[7]], [])

Expected Output: [7]

Explanation: Minimum valid 1x1 matrix with no blockers returns its single value.

Input: ([[1, 2, 3], [4, 5, 6], [7, 8, 9]], [])

Expected Output: [1, 2, 3, 6, 9, 8, 7, 4, 5]

Explanation: Source Example 1: ordinary 3x3 spiral, the outer ring clockwise and then the center.

Hints

  1. Every move depends only on the current cell, the current direction and which neighbouring cells are still available, so the walk can be reproduced step by step.
  2. A blocker, a cell outside the matrix and an already visited cell all affect the walk in the same way.
  3. The walk ends the first time none of the four directions from the current cell leads to an available cell, even if some open cells remain.

Loading coding console...

Show the approach

Approach

Simulate the walk exactly as the rules describe. Keep an m x n grid of unavailable flags: mark every blocker before the walk starts and mark each cell as it is visited, so one test (inside the matrix and not flagged) decides whether a cell is available. Index the directions 0 = right, 1 = down, 2 = left, 3 = up, so a clockwise turn is d -> (d + 1) mod 4. Start at (0, 0) facing right, flag it and output matrix[0][0]. On every step try d, d + 1, d + 2 and d + 3 (mod 4) in that order; the first direction whose next cell is available becomes the current direction, and the walk moves there, flags the cell and appends its value. If none of the four works, stop.

Invariant: the flagged cells are exactly the blockers plus the visited cells, and the output lists the visited cells in the order they were entered. Because the walk tries the current direction first and then each clockwise turn in order, it makes precisely the move the rules require, and it stops exactly when no direction leads to an available cell. Blockers are never entered, and open cells the walk never reaches are never output. With no blockers the simulation reproduces the ordinary clockwise spiral.

Edge cases: a 1x1 matrix, or a matrix in which every cell except (0, 0) is blocked, returns [matrix[0][0]]; single rows and single columns turn at the edge immediately; a blocker can end the walk early and leave open cells unreached.

Each cell is entered at most once and each step checks at most four neighbours, so the walk costs O(m * n) time; marking the blockers costs O(len(blocked)), which is at most m * n.

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