Solution: Spiral Matrix

Let's solve the Spiral Matrix problem using the Matrices pattern.

Statement#

Given an m×nm\times n matrix, return an array containing the matrix elements in spiral order, starting from the top-left cell.

Constraints:

  • 11\leq matrix.length 10\leq 10
  • 11\leq matrix[i].length 10\leq 10
  • 100-100\leq matrix[i][j] 100\leq 100

Solution#

We’ll maintain a variable, direction, which indicates the direction we need to travel in. It will store the value of either 11 or 1-1. Its value will change based on the following rules:

  • It will be 11 if we’re traveling in the following directions:

    • Left to right (horizontal)
    • Top to bottom (vertical)
  • It will be 1-1 if we’re traveling in the following directions:

    • Right to left (horizontal)
    • Bottom to top (vertical)

Here’s how the algorithm works:

  1. We initialize the following variables:

    • rows, cols = len(matrix), len(matrix[0]): These are the total number of rows and columns in the matrix, respectively.
    • row, col = 0, -1: These are the pointers used to traverse the matrix.
    • direction = 1: This indicates the direction we need to travel in. It is initialized to 11 since our first traversal will be in the left to right (horizontal) direction.
    • result = []: This array stores the matrix elements in spiral order.
  2. We start the traversal from the top left cell in the matrix:

    1. We first travel from left to right in a row by adding the direction variable to col while keeping the value of row unchanged. At each iteration, we will add matrix[row][col] to result. At the end of this row traversal, we decrement rows by 11 because if we traverse a column after this, we’ll traverse one less element.
    2. Next, we travel from top to bottom in a column by adding the direction variable to row while keeping the value of col unchanged. At each iteration, we will add matrix[row][col] to result. At the end of this column traversal, we decrement cols by 11 because if we traverse a row after this, we’ll traverse one less element.
  3. We reverse the direction by multiplying the direction variable by 1-1:

    1. Now, we travel from right to left in a row by adding the direction variable (which is now 1-1) to col while keeping the value of row unchanged. At each iteration, we will add matrix[row][col] to result. At the end of this row traversal, we decrement rows by 11 because if we traverse a column after this, we’ll traverse one less element.

    2. Next, we travel from bottom to top in a col by adding the direction variable (which is now 1-1) to row while keeping the value of col unchanged. At each iteration, we will add matrix[row][col] to result. At the end of this column traversal, we decrement cols by 11 because if we traverse a row after this, we’ll traverse one less element.

  4. We again reverse the direction by multiplying the direction variable by 1-1.

  5. The four steps above are repeated until all the cells of the matrix have been traversed, after which result stores the spiral order, so we return result.

Let’s look at the following illustration to get a better understanding of the solution:

Created with Fabric.js 3.6.6 rows = 4, cols = 3row = 0, col = -1direction = 1We will start by traversing the first row of the matrix.

1 of 20

Created with Fabric.js 3.6.6 rows = 4, cols = 3direction = 1col += directionrow = 0, col = 0We are currently moving in the left to right direction.We add matrix[0][0] to the result array.

2 of 20

Created with Fabric.js 3.6.6 rows = 4, cols = 3direction = 1col += directionrow = 0, col = 1We are currently moving in the left to right direction.We add matrix[0][1] to the result array.

3 of 20

Created with Fabric.js 3.6.6 rows = 4, cols = 3direction = 1col += directionrow = 0, col = 2We are currently moving in the left to right direction.We add matrix[0][2] to the result array.

4 of 20

Created with Fabric.js 3.6.6 rows -= 1rows = 3, cols = 3We decrement rows because if we traverse a column after this, one less element in that column needs to be traversed so that the lastest elementin the result array is not traversed twice.We will now traverse the matrix from top to bottom.

5 of 20

Created with Fabric.js 3.6.6 rows = 3, cols = 3direction = 1row += directionrow = 1, col = 2We are currently moving in the top to bottom direction.We add matrix[1][2] to the result array.

6 of 20

Created with Fabric.js 3.6.6 rows = 3, cols = 3direction = 1row += directionrow = 2, col = 2We are currently moving in the top to bottom direction.We add matrix[2][2] to the result array.

7 of 20

Created with Fabric.js 3.6.6 rows = 3, cols = 3direction = 1row += directionrow = 3, col = 2We are currently moving in the top to bottom direction.We add matrix[3][2] to the result array.

8 of 20

Created with Fabric.js 3.6.6 cols -= 1rows = 3, cols = 2We decrement cols because if we traverse a row after this, one less element in that row needs to be traversed so that the lastest elementin the result array is not traversed twice.We will now traverse the matrix from top to bottom.

9 of 20

Created with Fabric.js 3.6.6 rows = 3, cols = 2direction = 1row += directionrow = 3, col = 2We are currently moving in the top to bottom direction.We add matrix[3][2] to the result array.

10 of 20

Created with Fabric.js 3.6.6 rows = 3, cols = 2direction = -1col += directionrow = 3, col = 1We are currently moving in the right to left direction.We add matrix[3][1] to the result array.

11 of 20

Created with Fabric.js 3.6.6 rows = 3, cols = 2direction = -1col += directionrow = 3, col = 0We are currently moving in the right to left direction.We add matrix[3][0] to the result array.

12 of 20

Created with Fabric.js 3.6.6 rows -= 1rows = 2, cols = 2We decrement rows because if we traverse a column after this, one less element in that column needs to be traversed so that the lastest elementin the result array is not traversed twice.We will now traverse the matrix from bottom to top.

13 of 20

Created with Fabric.js 3.6.6 rows = 2, cols = 2direction = -1row += directionrow = 2, col = 0We are currently moving in the bottom to top direction.We add matrix[2][0] to the result array.

14 of 20

Created with Fabric.js 3.6.6 rows = 2, cols = 2direction = -1row += directionrow = 1, col = 0We are currently moving in the bottom to top direction.We add matrix[1][0] to the result array.

15 of 20

Created with Fabric.js 3.6.6 cols -= 1rows = 2, cols = 1direction *= -1We decrement cols because if we traverse a row after this, one less element in that row needs to be traversed so that the lastest elementin the result array is not traversed twice.We reverse the sign of direction since we will now be traversing the matrix from right to left.

16 of 20

Created with Fabric.js 3.6.6 rows = 2, cols = 1direction = 1col += directionrow = 1, col = 1We are currently moving in the left to right direction.We add matrix[1][1] to the result array.

17 of 20

Created with Fabric.js 3.6.6 rows -= 1rows = 1, cols = 1We decrement rows because if we traverse a column after this, one less element in that column needs to be traversed so that the lastest elementin the result array is not traversed twice.We will now traverse the matrix from top to bottom.

18 of 20

Created with Fabric.js 3.6.6 rows = 1, cols = 1direction = 1row += directionrow = 2, col = 1We are currently moving in the top to bottom direction.We add matrix[2][1] to the result array.

19 of 20

Created with Fabric.js 3.6.6 cols -= 1rows = 1, cols = 0We decrement cols because if we traverse a row after this, one less element in that row needs to be traversed so that the lastest elementin the result array is not traversed twice.Since cols is 0, all the cells have been traversed, and we return result.

20 of 20

Let’s have a look at the code for the algorithm we just discussed:

Spiral Matrix

Time complexity#

The time complexity of this solution is O(m×n)O(m \times n) since each cell of the matrix is traversed.

Space complexity#

The space complexity of this solution is O(1)O(1) since no extra space is used.

Spiral Matrix

Final Remarks