Open In App

JavaScript Program to Print Given Matrix in Spiral Form

Last Updated : 06 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Write a JavaScript program to print a given 2D matrix in spiral form.

You are given a two-dimensional matrix of integers. Write a program to traverse the matrix starting from the top-left corner which moves right, bottom, left, and up in a spiral pattern until all the elements are visited. Let us understand it with the examples and figures given below:

Examples:

Example 1:

Input: matrix = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
Output: [1 2 3 6 9 8 7 4 5]
Untitled-drawing-(2)

Spiral Matrix Example-1

Example 2:

Input: matrix = [[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]]
Output: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
Untitled-drawing-(4)

Spiral Matrix Example-2

Method 1: Using Boundary Traversal Approach

To print a given matrix in a spiral form we initialize boundaries to track the matrix’s edges. Then iterate through the matrix, printing elements in a clockwise spiral pattern: top row, right column, bottom row, left column. Adjust boundaries after each step and continue until all elements are printed.

  • Initialize four variables to represent the boundaries of the matrix:
    • top: The topmost row.
    • bottom: The bottommost row.
    • left: The leftmost column.
    • right: The rightmost column.
  • Iterate over all the elements of the matrix:
    • Print all elements of the top row from left to right and increment the top pointer to move to the next row.
    • Now, print all elements of the right column from top to bottom and decrement the right pointer to the previous column.
    • Check that, if the top pointer is still less than or equal to the bottom boundary.
    • If yes, then print all elements of the bottom row from right to left and decrement the bottom to its previous row.
    • Again check if the left pointer is still less than or equal to the right boundary.If yes, then print all elements of the left column from bottom to top and increment the left to its next column.
  • Repeat the above steps until all elements are printed.

Example: Below is the implementation of the above approach:

Javascript




// JavaScript code for the above approach
  
function printSpiral(matrix) {
    let result = [];
    let top = 0;
    let bottom = matrix.length - 1;
    let left = 0;
    let right = matrix[0].length - 1;
  
    // Loop while the elements 
    // are within the boundaries.
    while (top <= bottom
        && left <= right) {
        // Print top row
        for (let i = left;
            i <= right; i++) {
            result.push(matrix[top][i]);
        }
        // Move the top boundary down.
        top++;
  
        // Print right column
        for (let i = top;
            i <= bottom; i++) {
            result.push(matrix[i][right]);
        }
        // Move the right boundary to the left.
        right--;
  
        // Check if there are more rows
        if (top <= bottom) {
            // Print bottom row
            for (let i = right;
                i >= left; i--) {
                result.push(matrix[bottom][i]);
            }
            // Move the bottom boundary up.
            bottom--;
        }
  
        // Check if there are more columns
        if (left <= right) {
            // Print left column
            for (let i = bottom;
                i >= top; i--) {
                result.push(matrix[i][left]);
            }
            // Move the left boundary to the right.
            left++;
        }
    }
  
    // Print the result
    console.log(result.join(' '));
}
  
// Example
const matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]
];
printSpiral(matrix);


Output

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

Time Complexity: O(m * n): The time complexity of this code is O(m * n), where ‘m’ is the number of rows in the matrix, and ‘n’ is the number of columns in the matrix. This is because we visit each element in the matrix exactly once in a linear fashion.

Space Complexity: O(m * n): The space complexity is O(m * n) as well. The primary space consumption comes from the result array, which stores all the elements of the matrix in spiral order. The size of this array is directly proportional to the number of elements in the matrix, which is ‘m * n’.

Method 2: Using Simulation Approach

  • We are given a matrix of ‘N’ rows and ‘M’ columns.
  • Use a visited array where vis[n][m] indicates whether the cell at row ‘n’ and column ‘m’ has been visited.
  • Our current position is denoted by (n, m), and we’re facing a certain direction d. We have to visit all the N x M cells in the matrix.
  • As we traverse through the matrix, we continuously calculate a cell’s next position, denoted as (nrow, ncol).
  • If the cell’s position is within the bounds of the matrix and has not been visited (!vis[nrow][nrow]), it becomes our next position.
  • If the cell’s position is out of bounds or has already been visited, we change our next position to the one by performing a clockwise turn.

Example: Below is the implementation of the above approach:

Javascript




// JavaScript code for the above approach
  
function spiralOrder(matrix) {
    let result = [];
  
    if (matrix.length === 0) {
        return result;
    }
  
    let N = matrix.length;
    let M = matrix[0].length;
    // Create a visited matrix
    let vis = new Array(N);
    for (let n = 0; n < N; n++) {
        vis[n] = new Array(M).fill(false);
    }
  
    let dx = [0, 1, 0, -1];
    let dy = [1, 0, -1, 0];
    let n = 0, m = 0, d = 0;
  
    // Traverse through the matrix
    for (let i = 0; i < N * M; i++) {
        result.push(matrix[n][m]);
        vis[n][m] = true;
  
        // Calculate the next 
        // cell's position
        let nrow = n + dx[d];
        let ncol = m + dy[d];
  
        // Check the valid positions 
        // of the cell
        if (nrow >= 0 && nrow < N
            && ncol >= 0 && ncol < M
            && !vis[nrow][ncol]
        ) {
            n = nrow;
            m = ncol;
        } else {
            // Perform a clockwise 
            // turn to change direction
            d = (d + 1) % 4;
            n += dx[d];
            m += dy[d];
        }
    }
  
    return result.join(' ');
}
  
// Example
const matrix = [
    [1, 2, 3, 4],
    [12, 13, 14, 5],
    [11, 16, 15, 6],
    [10, 9, 8, 7],
];
  
let spiralResult = spiralOrder(matrix);
console.log(spiralResult);


Output

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

Time Complexity: O(N * M).

Space Complexity: O(N * M).

Method 3: Using Recursion in JavaScript

  • Create a recursive function that takes a matrix and four variables: k (starting row index), m (ending row index), l (starting column index), and n (ending column index) as the parameters.
  • As a base case, the starting index should be less than or equal to the ending index for both rows and columns.
  • Now print the boundary elements in a clockwise manner as given in below steps:
  • First, print the top row elements. This means print the elements of the k-th row from column index l to n. Then increment the value of k.
  • Next, print the right column elements. Print the last column from row index k to m. Then decrease the value of n.
  • If k is greater than m, print the bottom row elements. That is, the elements of the (m-1)th row from column n-1 to l and decrement the value of m.
  • If l is less than n, print the left column elements of the l-th column from the (m-1)th row to k and increment the value of l.
  • Recursively call the function with the updated values of starting and ending indices for rows and columns.

Example: Below is the implementation of the above approach:

Javascript




// JavaScript code for the above approach
  
function printSpiralRecursive(matrix, k, m, l, n) {
    // Base case
    if (k > m || l > n) {
        return '';
    }
  
    let result = '';
    // Print the top row from left to right
    for (let i = l; i <= n; i++) {
        result += matrix[k][i] + ' ';
    }
    // Increment the row index from start
    k++;
  
    // Print the right column from top to bottom
    for (let i = k; i <= m; i++) {
        result += matrix[i][n] + ' ';
    }
    // Decrement the column index from end
    n--;
  
    // Check if there is a bottom row to print
    if (k <= m) {
        for (let i = n; i >= l; i--) {
            result += matrix[m][i] + ' ';
        }
        // Decrement the row index from end
        m--;
    }
  
    // Check if there is a left column to print
    if (l <= n) {
        for (let i = m; i >= k; i--) {
            result += matrix[i][l] + ' ';
        }
        // Increment the column index from start
        l++;
    }
  
    // Recursive Call
    return result +
        printSpiralRecursive(matrix, k, m, l, n);
}
  
// Function to print the matrix in spiral form
function printSpiral(matrix) {
    const rows =
        matrix.length;
    const columns =
        matrix[0].length;
    const spiralResult =
        printSpiralRecursive(matrix, 0, rows - 1,
            0, columns - 1);
    console.log(spiralResult);
}
  
// Example
const matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
];
  
printSpiral(matrix);


Output

1 2 3 6 9 8 7 4 5 

Time Complexity: O(N*M). To traverse the entire matrix O(N*M) time is required.

Space Complexity: O(1). As we do not use any external data structure here, there is constant space. But obviously the algorithm will consume a recursive stack space of O(n).

Method 4: Using Depth First Search (DFS)

  • Create an array of N*M for marking the visited cells so far. Initially, all the cells will be unvisited.
  • Create arrays called dx (for rows) and dy (for columns) to represent the four possible adjacent directions for each cell.
  • Now, in the recursive DFS function, the current row, column and the direction will be the parameters.
  • As a base case, check if the current cell is within the bounds of the given matrix and if the cell has not been visited earlier.
  • If not, then mark it as visited and print its value.
  • Calculate the value of the next row and column by adding the respective values from dx and dy arrays. Make a recursive call in the new indices of those directions.
  • When one traversal gets complete, change the direction to the next clockwise direction to print the matrix spirally.
  • Start the DFS from the top-left corner of the given matrix which will be the first cell.

Example: Below is the implementation of the above approach:

Javascript




// JavaScript code for the above approach
  
function spiralDFS(matrix) {
    const N = matrix.length;
    const M = matrix[0].length;
  
    // Initialize a visited array 
    let vis = new Array(N);
    for (let n = 0; n < N; n++) {
        vis[n] = new Array(M).fill(false);
    }
  
    // Row and column directions for 
    // right, down, left, and up
    const dx = [0, 1, 0, -1];
    const dy = [1, 0, -1, 0];
  
    let i = 0;
    let row = 0;
    let col = 0;
  
    const result = [];
  
    // DFS function
    function dfs(row, col) {
        // Base case: Check if the current 
        // cell is within bounds and unvisited
        if (row < 0 || row >= N ||
            col < 0 || col >= M ||
            vis[row][col]) {
            return;
        }
  
        // Mark the cell as visited 
        // and add it to the result
        result.push(matrix[row][col]);
        vis[row][col] = true;
  
        // Calculate the next row and column
        const nrow = row + dx[i];
        const ncol = col + dy[i];
  
        // Recursively call DFS with the new indices
        dfs(nrow, ncol);
  
        // If DFS completes in the current 
        // direction, change direction clockwise
        if (nrow < 0 || nrow >= N ||
            ncol < 0 || ncol >= M ||
            vis[nrow][ncol]) {
            i = (i + 1) % 4;
            const nrow = row + dx[i];
            const ncol = col + dy[i];
            dfs(nrow, ncol);
        }
    }
  
    // Start DFS from the top-left 
    // corner of the matrix
    dfs(row, col);
  
    console.log(result.join(' '));
}
  
// Example
const matrix = [
    [1, 2, 3],
    [6, 5, 7],
    [4, 8, 11],
    [12, 0, 16]
];
  
spiralDFS(matrix);


Output

1 2 3 7 11 16 0 12 4 6 5 8

Time Complexity: O(N*M) To traverse the entire matrix O(m*n) time is required.

Space Complexity: O(N*M) We use an external data structure here, which is a 2D visited matrix. Also, the algorithm will consume a recursive stack space.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads