Step-by-Step Guide to Printing a 2D Array in Spiral Order
Nitish Kumar Singh
Jan 25, 2025Printing a 2D array in spiral order is a common problem in practicing data structures and algorithms that helps us understand and write logical code.
When we write code for this problem, we can understand how to use loops and conditions according to the problem. In this post, we are going to understand each step for building logic for this problem and write a Java method that prints the given 2D array spirally.
Before anything, first, see and understand what happens when we move spirally in a 2D array. When we move spirally in a 2D array, the below things happen:
- First, we move on the top edge with a fixed row index, and the column index increases up to
endCol
. - Then, we move on the right edge with a fixed column index, and the row index increases up to
endRow
. - Then, on the bottom edge with a fixed row, the column index decreases up to
startCol
. - Finally, on the left edge with a fixed column, the row index decreases up to
startRow + 1
.
Here, startRow
, endRow
, startCol
, and endCol
are indices of the edges of one full spiral round, and they change after each spiral round, with startRow
and startCol
increasing by 1, and endRow
and endCol
decreasing by 1.
Using the above information, we have to build logic. This problem can be solved with two different approaches.
First, we run a loop for n times, where n is the number of spiral rounds we can move. The second approach is to run a loop for the number of cells in the given array. We will discuss both approaches and write code for them.
Round-by-Round Spira Movement
In this approach, we will focus on how many spiral rounds we can move using a while
loop, and under this while loop, we print all found boundaries of one spiral round using four inner for loops. To write the code, we need to understand the points below:
- The first question is how to make the condition for a while loop. In the above-given picture, we can see spiral rounds are possible until
startRow <= endRow
andstartCol <= endCol
, where equality is possible when the number of rows, columns, or both are odd. - What is the condition for the 4 for loops? The loops for printing the top, right, bottom, and left edges run from
startCol
toendCol
,startRow+1
toendRow
,endCol-1
tostartCol
, andendRow-1
tostartRow+1
accordingly. - After printing each spiral round, we increase
startRow
andstartCol
by 1 and decreaseendRow
andendCol
by 1 to move to the inner spiral round.
So, the complete Java code for printing using this approach is as below.
public static void printSpiralByRoundWise(int[][] matrix) {
int startRow = 0, endRow = matrix.length - 1;
int startCol = 0, endCol = matrix[0].length - 1;
while (startRow <= endRow && startCol <= endCol) {
// Print the top row (left to right)
for (int col = startCol; col <= endCol; col++) {
System.out.print(matrix[startRow][col] + " ");
}
// Because right edge print from startRow+1
startRow++;
// Print the rightmost column (top to bottom)
for (int row = startRow; row <= endRow; row++) {
System.out.print(matrix[row][endCol] + " ");
}
// Because bottom edge print from endCol-1
endCol--;
// Print the bottom row (right to left)
// The startRow <= endRow is insure not repeat printing of same eadge in odd numbers of rows
if (startRow <= endRow) {
for (int col = endCol; col >= startCol; col--) {
System.out.print(matrix[endRow][col] + " ");
}
// Because left edge print from endRow-1
endRow--;
}
// Print the leftmost column (bottom to top)
// The startCol <= endCol is insure not repeat printing of same eadge in odd numbers of columns
if (startCol <= endCol) {
for (int row = endRow; row >= startRow; row--) {
System.out.print(matrix[row][startCol] + " ");
}
// For moving to next inner spiral round
startCol++;
}
}
}
In the above code, we add loops that print the bottom and left edges in conditions to avoid repeated printing. For example, when the number of rows is 3, two rows are already printed in the first spiral round, and startRow
increases to 1, while endRow
decreases to 1.
So, in the second spiral round, only one edge is available, which is the top. After printing the top edge, startRow
increases to 2, which is greater than endRow
, which is 1.
Cell-by-Cell Spiral Movement
In this approach, we will do exactly what happens when moving spirally in a 2D array. This means we run a single for loop for m * n
times, where m and n are the numbers of rows and columns. In each iteration, we prepare for printing the next spiral cell's indices.
For this, we declare two variables row = 0
and col = 0
, and then:
- First, increase
col
one by one up toendCol
. - Then, increase
row
up toendRow
. - Decrease
col
up tostartCol
. - Finally, decrease
row
up tostartRow + 1
.
After completing one spiral round, we move to the next spiral round by changing variables as follows: col++
, startRow++
, startCol++
, endRow--
, and endCol--
.
The big question is when we will increase row or col and when we will decrease it. If we think carefully, we see that when moving on the top edge of a spiral round, row == startRow
. When on the right edge, col == endCol
. This means we can increment col at first until row == startRow && col < endCol
.
Here, we do not use col <= endCol
because we are preparing for the next cell, not for the current cell. This means when col is endCol - 1
, it already increases to col == endCol
in the previous iteration and has already been printed.
In the current iteration, the condition row == startRow && col < endCol
fails, and we move to the next condition: col == endCol && row < endRow
for the right edge, and we increment row. This is like printing the current spiral cell in the current iteration while also preparing for the next.
Now, for the rest of the conditions for decreasing row and col and preparing for the next inner spiral, you can see the complete code of printing using this approach below.
public static void printSpiralCellsWise(int[][] matrix){
int startRow = 0, endRow = matrix.length-1;
int startCol = 0, endCol = matrix[0].length -1;
int row=0, col=0;
for(int k=0;k<matrix.length*matrix[0].length;k++){
System.out.print(matrix[row][col] + " ");
if (row == startRow && col < endCol) col++; // Move right
else if (col == endCol && row < endRow) row++; // Move down
else if (row == endRow && col > startCol) col--; // Move left
else if (col == startCol && row > startRow + 1) row--; // Move up
else {
// Prepare for the next inner spiral
col++;
startRow++;
startCol++;
endRow--;
endCol--;
}
}
}
The conditions used above come from optimizing the conditions below in two iterations.
// First time conditions
public static void printSpiralCellsWise(int[][] matrix){
int startRow = 0, endRow = matrix.length-1;
int startCol = 0, endCol = matrix[0].length -1;
int direction=0;
int row=0, col=0;
for(int k=0;k<matrix.length*matrix[0].length;k++){
System.out.print(matrix[row][col] + " ");
if(direction==0){
if (col<endCol) col++;
else{
direction = 1;
row++;
}
}else if (direction==1) {
if(row<endRow) row++;
else {
direction = 2;
col--;
}
}else if (direction==2) {
if(col>startCol) col--;
else {
direction = 3;
row--;
}
}else if (direction==3) {
if(row>startRow+1) row--;
else {
direction = 0;
col++;
startRow++; startCol++;
endRow--; endCol--;
}
}
}
}
// second time conditions
public static void printSpiralCellsWise(int[][] matrix){
int startRow = 0, endRow = matrix.length-1;
int startCol = 0, endCol = matrix[0].length -1;
int row=0, col=0;
for(int k=0;k<matrix.length*matrix[0].length;k++){
System.out.print(matrix[row][col] + " ");
if(row==startRow){
if (col<endCol) col++; else row++;
}else if (col==endCol) {
if(row<endRow) row++; else col--;
}else if (row==endRow) {
if(col>startCol) col--; else row--;
}else if (col==startCol) {
if(row>startRow+1) row--;
else {
col++;
startRow++; startCol++;
endRow--; endCol--;
}
}
}
}
What do you think? Which approach is more efficient in terms of both time and space? Of course, the time complexity is the same, O(m*n)
, in both approaches, but readability has improved in the second approach by removing extra loops.
According to my understanding, the second approach is more efficient in terms of space. This is because, in the second approach, only 6 variables are created irrespective of the number of cells. However, in the first approach, the variable count is 4
fixed variables + 4*r
more variables, where r
is the number of spiral rounds possible.
I know for loop variables are local and discarded after each while iteration, but constantly creating and discarding variables in each while iteration might have some impact. What do you think? Share your thoughts in the comments.
This is a complete step-by-step guide and something that I have learned while solving this problem. I hope you enjoy reading it and find it informative, helpful, and enjoyable. Thanks for reading, and happy coding!