Attempting the Spiral Matrix

HopeGiometti
8 min readJul 14, 2020

--

I’m not going to lie to you and tell you that solving the Spiral Matrix problem is easy. It isn’t. This problem is challenging. Sometimes I look at the solution and still feel a little lost. However, this problem is a routine interview question. I’ve actually been asked to solve it during an interview myself. So, I’m hoping that by writing this tutorial I can help the both of us be able to understand and solve this problem a little bit more easily.

All that being said, let’s jump right in!

Me avoiding this problem for months because I found it too confusing

What even is the spiral matrix problem?

There are actually multiple problems referred to as the spiral matrix problem (search spiral on leet code if you’re curious!), but today I’m going to focus on the one that asks us to create the spiral matrix ourselves. Here is the problem statement:

Write a function that accepts an integer n and returns an n x n spiral matrix.

Don’t worry if you’re already feeling a little confused. Here’s a much easier visual representation of what the problem wants you to create:

A spiral matrix with a clockwise, inward spiral

Basically, you will be creating a matrix with a width of n, in this case 4 and a length of n, again 4, wherein all the numbers inside the matrix will move in a clockwise, inward spiraling pattern until they reach n², in this case 16.

Now that you hopefully understand the goal of this algorithm, let’s move on to our implementation of it.

The Solution: One more reason to love arrays

The basic goal for this implementation, is to move follow that dotted line on the image above and move around our spiral, filling in the numbers as we go. The key to this solution is knowing that with arrays we are able to freely assign any value to any index inside the array that we want. To clarify, let’s say we declared an empty array like so:

let myArray = []

We would then be able to insert a value at any index inside the array that we wanted, for example if we wanted to insert the value 7 at an index of 4, our array would look like this:

myArray[4] = 7
myArray = [null,null,null,null,7]

Keep this feature of arrays in mind as we carry on with our implementation of this solution!

The Solution: Our many, many variables

There are a number of variables we are going to use in this problem and it’s important to understand their roles and how they work in this problem.

Let’s start by taking a look at a very simple spiral matrix:

3x3 Spiral Matrix

To create this matrix, we are going to need four variables that will allow us to keep track of where we are in the matrix as we construct it. As you can see in the image above, I’ve called these variables Start Column, End Column, Start Row, and End Row. While the value of these variable will change as we create our matrix, these variables will be initialized as such:

Both of the start variables (start row and start column) will begin with values of 0. We start with 0 as these values are referencing indexes in the the final array of arrays that will make up our matrix and as we know arrays begin with an index value of 0.

Our end variables (end row and end column) will also share a starting value, though this value is dependent on n. Although our matrix, as mentioned above, has both a length and width of n, since we are working with arrays we will assign our end row and end column variables a value of n-1.

The solution: Four for loops

I think what I really struggled to understand the first time I attempted this solution was that we are going to be building this matrix in the same spiraling pattern that we want to build it with. This might be obvious to you, but what I’m trying to say is that our construction of our matrix will follow the red arrow or blue dotted line on diagrams above. Basically, we will first construct our top row, then our right side column, then our bottom row, then our left side column, etc., until we reach the center of our spiral. To do this, we will need four for loops that will each be responsible for creating a different side of matrix.

The solution: JK there’s a fifth for loop

Now that we have a bit of a broad understanding of how this solution is going to be working, I’m going to quickly backtrack a little because the first thing we need to do to solve this problem is create an array of arrays that will be our final matrix. We can call this array anything we want, but I’m going to name mine “results”.

Results, as I said before, is going to be an array of arrays. Specifically, it’s going to be an array of n arrays and to make sure of this we will write another for loop that will allow us to push in the appropriate number of arrays into our results array.

function spiralMatrix(n){
let results = []
for (let i = 0; i < n; i++){
results.push([])
}
}

The Solution: Our first for loop

Now that we have our results array create and filled with the correct number of subarrays, we can move on to declaring our variables and actually begin constructing our final matrix.

function spiralMatrix(n) {
let results = []
for (let i = 0; i < n; i++) {
results.push([])
}

let startColumn = 0
let endColumn = n - 1
let startRow = 0
let endRow = n -1
let counter = 1}

Before we move on to writing our first for loop, you’ve probably noticed that I declared another variable, called counter. The counter variable is going to be what we use to fill in the values of our matrix and will be incremented each time we add a new value to our final results array.

The next step in our solution will be writing our for loop that will allow us to construct the top row of our matrix. To do this, we need to understand that the top row of matrix spans from start column to our end column.

for (let i = startColumn; i <= endColumn; i++) {
results[startRow][i] = counter
counter++
}

Remember that helpful feature of arrays we discussed above? We are going to be using that feature to assign values at the specific indices we want. For example, at index 0 (the current value of startRow) of results (an array itself) we want to assign that value of counter to the subarray with an index of i.

I understand that the creation of that for loop may still be a bit confusing, but hopefully you have a general understanding of how it is working. Before we move on for our first for loop, however, we have to do one more thing.

I mentioned above that values of our four start/end variables are going to change as we build our matrix and here is where that starts to happen. Since our first for loop filled our top row, we will now need to increment the value of our start row variable.

for (let i = startColumn; i <= endColumn; i++) {
results[startRow][i] = counter
counter++
}
startRow++

Now that we have an understanding of how our first for loop works, we are very close to solving this problem.

The Solution: A while loop that I forgot but you definitely shouldn’t!

Before we get to our last three for loops, there is one last type of loop we will need to employ to solve this problem: a while loop. We will wrap our four for loops responsible for constructing our matrix inside this while loop. This will allow us to terminate our matrix building at the appropriate time and without it our for loops would endlessly run.

The Solution: Our long, semi-complicated finale

Now that we’ve gone over almost every step to this problem, all that we have left to do is to understand the slight different between the for loop we just wrote and our remaining three.

function spiralMatrix(n) {
let results = []
for (let i = 0; i < n; i++) {
results.push([])
}

let startColumn = 0
let endColumn = n - 1
let startRow = 0
let endRow = n -1
let counter = 1 while (startColumn <= endColumn && startRow <= endRow) {

//top row
for (let i = startColumn; i <= endColumn; i++) {
results[startRow][i] = counter
counter++
}
startRow++
//right side
for (let i = startRow; i <= endRow; i++) {
results[i][endColumn] = counter
counter++
}
endColumn--
//bottom row
for (let i = endColumn; i >= startColumn; i--) {
results[endRow][i] = counter
counter++
}
endRow--
//left side
for (let i = endRow; i >= startRow; i--) {
results[i][endRow] = counter
counter++
}
startColumn++
}

return results
}

As you can see, our for loops work in a very similar manner with just slight differences in where they begin and end, what indices they fill in our results array, and what start/end variable is changed upon their completion.

To understand how each for loop works, remember that we want to build our matrix in a spiral pattern. I’ve labeled each for loop to help you understand which part of matrix each for loop is responsible for. Ultimately, if you are feeling a little lost on how each for loop is working, trying following this code and drawing out the matrix as you go. A lot of what can be confusing about this problem is not the actual code, but keeping track of each variable as you build your matrix.

The spiral matrix problem is definitely not an easy one to attempt, so don’t be discouraged if you are still feeling a little lost and confused even after reading this tutorial. I’ve watched and read tons of tutorials and guides to this problem and it’s only recently that I feel like I fully understand it. My best advice for figuring out this problem is one that I always say at the end of my posts, but it definitely applies here: practice. No matter how many tutorials you read of this, or any, algorithm the best way to get better at solving these types of problems is trying them on your own!

Good luck and happy coding!

Me, no longer intimated by this problem

--

--

No responses yet