👋
Welcome to my blog!

Spiral Traverse

Navigate the intricacies of traversing a matrix in a spiral order to capture elements in a mesmerizing sequence.

Spiral Traverse
array
medium

Published At

3/5/2023

Reading Time

~ 4 min read

Write a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m) and returns a one-dimensional array of all the array's elements in spiral order.

Spiral order starts in the top left corner of the two-dimensional array, goes to the right, and proceeds in a spiral pattern all the way until every element has been visited.

Sample Input

js
array = [
  [1,   2,  3, 4],
  [12, 13, 14, 5],
  [11, 16, 15, 6],
  [10,  9,  8, 7],
]
js
array = [
  [1,   2,  3, 4],
  [12, 13, 14, 5],
  [11, 16, 15, 6],
  [10,  9,  8, 7],
]

Sample Output

js
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
js
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

Hints

Hint 1

You can think of the spiral that you have to traverse as a set of rectangle perimeters that progressively get smaller (i.e., that progressively move inwards in the two-dimensional array).

Hint 2

Going off of Hint #1, declare four variables: a starting row, a starting column, an ending row, and an ending column. These four variables represent the bounds of the first rectangle perimeter in the spiral that you have to traverse. Traverse that perimeter using those bounds, and then move the bounds inwards. End your algorithm once the starting row passes the ending row or the starting column passes the ending column.

Hint 3

You can solve this problem both iteratively and recursively following very similar logic.

Optimal Space & Time Complexity

O(n) time | O(n) space - where n is the total number of elements in the array

Solution-1
js
// O(n) time | O(n) space - where n is the total number of elements in the array
function spiralTraverse(array) {
  // Write your code here.
 
  let arr = []
  let startRow = 0, endRow = array.length - 1
  let startCol = 0, endCol = array[0].length - 1
  
  while (startRow <= endRow && startCol <= endCol)  {  
    for (let col = startCol; col <= endCol; col++) {
      arr.push(array[startRow][col])
    }
  
    for (let row = startRow + 1; row <= endRow; row++) {
      arr.push(array[row][endCol])
    }
  
    for (let col = endCol - 1; col >= startCol; col--) {
      if (startRow === endRow) break
      arr.push(array[endRow][col])
    }
  
    for (let row = endRow - 1; row > startRow; row--) {
      if (startCol === endCol) break
      arr.push(array[row][startCol])
    }
 
    startRow++;
    endRow--;
    startCol++;
    endCol--;
  }
  
  console.log(arr)
  return arr  
}
 
Solution-1
js
// O(n) time | O(n) space - where n is the total number of elements in the array
function spiralTraverse(array) {
  // Write your code here.
 
  let arr = []
  let startRow = 0, endRow = array.length - 1
  let startCol = 0, endCol = array[0].length - 1
  
  while (startRow <= endRow && startCol <= endCol)  {  
    for (let col = startCol; col <= endCol; col++) {
      arr.push(array[startRow][col])
    }
  
    for (let row = startRow + 1; row <= endRow; row++) {
      arr.push(array[row][endCol])
    }
  
    for (let col = endCol - 1; col >= startCol; col--) {
      if (startRow === endRow) break
      arr.push(array[endRow][col])
    }
  
    for (let row = endRow - 1; row > startRow; row--) {
      if (startCol === endCol) break
      arr.push(array[row][startCol])
    }
 
    startRow++;
    endRow--;
    startCol++;
    endCol--;
  }
  
  console.log(arr)
  return arr  
}
 
Solution-2
js
function spiralTraverse(array) {
  const result = []
  spiralFill(array, 0, array.length - 1, 0, array[0].length - 1, result)
  return result
}
 
function spiralFill(array, startRow, endRow, startCol, endCol, result) {
  if (startRow > endRow || startCol > endCol) return;
 
  for (let col = startCol; col <= endCol; col++) {
    result.push(array[startRow][col])
  }
 
  for (let row = startRow + 1; row <= endRow; row++) {
    result.push(array[row][endCol])
  }
 
  for (let col = endCol - 1; col >= startCol; col--) {
    if (startRow === endRow) break;
    result.push(array[endRow][col])
  }
 
  for (let row = endRow - 1; row > startRow; row--) {
    if (startCol === endCol) break
    result.push(array[row][startCol])
  }
 
  spiralFill(array, startRow + 1, endRow - 1, startCol + 1, endCol - 1, result)
  
}
Solution-2
js
function spiralTraverse(array) {
  const result = []
  spiralFill(array, 0, array.length - 1, 0, array[0].length - 1, result)
  return result
}
 
function spiralFill(array, startRow, endRow, startCol, endCol, result) {
  if (startRow > endRow || startCol > endCol) return;
 
  for (let col = startCol; col <= endCol; col++) {
    result.push(array[startRow][col])
  }
 
  for (let row = startRow + 1; row <= endRow; row++) {
    result.push(array[row][endCol])
  }
 
  for (let col = endCol - 1; col >= startCol; col--) {
    if (startRow === endRow) break;
    result.push(array[endRow][col])
  }
 
  for (let row = endRow - 1; row > startRow; row--) {
    if (startCol === endCol) break
    result.push(array[row][startCol])
  }
 
  spiralFill(array, startRow + 1, endRow - 1, startCol + 1, endCol - 1, result)
  
}

🌤️

Do you have any questions, or simply wish to contact me privately? Don't hesitate to shoot me a DM on Twitter.

Have a wonderful day.
Abhishek 🙏

Join My Exclusive Newsletter Community

Step into a world where creativity intersects with technology. By subscribing, you'll get a front-row seat to my latest musings, full-stack development resources, and exclusive previews of future posts. Each email is a crafted experience that includes:

  • In-depth looks at my covert projects and musings to ignite your imagination.
  • Handpicked frontend development resources and current explorations, aimed at expanding your developer toolkit.
  • A monthly infusion of inspiration with my personal selection of quotes, books, and music.

Embrace the confluence of words and wonder, curated thoughtfully and sent straight to your inbox.

No fluff. Just the highest caliber of ideas.