LeetCode – Spiral Matrix (Java)

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

For example, given the following matrix:

[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

You should return [1,2,3,6,9,8,7,4,5].

Java Solution 1

If more than one row and column left, it can form a circle and we process the circle. Otherwise, if only one row or column left, we process that column or row ONLY.

public class Solution {
    public ArrayList<Integer> spiralOrder(int[][] matrix) {
        ArrayList<Integer> result = new ArrayList<Integer>();
 
        if(matrix == null || matrix.length == 0) return result;
 
        int m = matrix.length;
        int n = matrix[0].length;
 
        int x=0; 
        int y=0;
 
        while(m>0 && n>0){
 
            //if one row/column left, no circle can be formed
            if(m==1){
                for(int i=0; i<n; i++){
                    result.add(matrix[x][y++]);
                }
                break;
            }else if(n==1){
                for(int i=0; i<m; i++){
                    result.add(matrix[x++][y]);
                }
                break;
            }
 
            //below, process a circle
 
            //top - move right
            for(int i=0;i<n-1;i++){
                result.add(matrix[x][y++]);
            }
 
            //right - move down
            for(int i=0;i<m-1;i++){
                result.add(matrix[x++][y]);
            }
 
            //bottom - move left
            for(int i=0;i<n-1;i++){
                result.add(matrix[x][y--]);
            }
 
            //left - move up
            for(int i=0;i<m-1;i++){
                result.add(matrix[x--][y]);
            }
 
            x++;
            y++;
            m=m-2;
            n=n-2;
        }
 
        return result;
    }
}

Similarly, we can write the solution this way:

public List<Integer> spiralOrder(int[][] matrix) {
    List<Integer> result = new ArrayList<Integer>();
    if(matrix==null||matrix.length==0||matrix[0].length==0)
        return result;
 
    int m = matrix.length;
    int n = matrix[0].length;
 
    int left=0;
    int right=n-1;
    int top = 0;
    int bottom = m-1;
 
    while(result.size()<m*n){
        for(int j=left; j<=right; j++){
            result.add(matrix[top][j]);
        }
        top++;
 
        for(int i=top; i<=bottom; i++){
            result.add(matrix[i][right]);
        }
        right--;
 
        //prevent duplicate row
        if(bottom<top)
            break;
 
        for(int j=right; j>=left; j--){
            result.add(matrix[bottom][j]);
        }
        bottom--;
 
        // prevent duplicate column
        if(right<left)
            break;
 
        for(int i=bottom; i>=top; i--){
            result.add(matrix[i][left]);
        }
        left++;
    }
 
    return result;
}

Java Solution 2

We can also recursively solve this problem. The solution’s performance is not better than Solution 1. Therefore, Solution 1 should be preferred.

public class Solution {
    public ArrayList<Integer> spiralOrder(int[][] matrix) {
        if(matrix==null || matrix.length==0) 
            return new ArrayList<Integer>();
 
        return spiralOrder(matrix,0,0,matrix.length,matrix[0].length);
    }
 
 
    public ArrayList<Integer> spiralOrder(int [][] matrix, int x, int y, int m, int n){
        ArrayList<Integer> result = new ArrayList<Integer>();
 
        if(m<=0||n<=0) 
            return result;
 
        //only one element left
        if(m==1&&n==1) {
            result.add(matrix[x][y]);
            return result;
        }
 
        //top - move right
        for(int i=0;i<n-1;i++){
            result.add(matrix[x][y++]);
        }
 
        //right - move down
        for(int i=0;i<m-1;i++){
            result.add(matrix[x++][y]);
        }
 
        //bottom - move left
        if(m>1){    
            for(int i=0;i<n-1;i++){
                result.add(matrix[x][y--]);
            }
        }
 
        //left - move up
        if(n>1){
            for(int i=0;i<m-1;i++){
                result.add(matrix[x--][y]);
            }
        }
 
        if(m==1||n==1)
            result.addAll(spiralOrder(matrix, x, y, 1, 1));
        else    
            result.addAll(spiralOrder(matrix, x+1, y+1, m-2, n-2));
 
        return result;
    }
}

15 thoughts on “LeetCode – Spiral Matrix (Java)”

  1. Here mine hope it will help…

    Unfortunately I had to add break lines… It’s less elegant.

    public static void main(String[] args) {
    int matrix [] [] =
    {
    {1,2,3},
    {4,5,6,},
    {7,8,9}
    };

    int nbLine = matrix.length;
    int nbCol = matrix[0].length;
    int nbLineB = 0;
    int nbColB = 0;
    int element = nbLine * nbCol;
    int index = 0;
    ArrayList response = new ArrayList();

    // While loop
    while( element > index)
    {
    // Move to the right
    if(element == index) break;
    for(int i =nbColB; i < nbCol; i++, index++)
    {
    response.add(matrix[nbColB][i]);
    }

    // Move Down
    if(element == index) break;
    for(int i = nbLineB+1; i = nbColB; i–, index++)
    {
    response.add(matrix[nbLine-1][i]);
    }

    nbLine–;
    nbLineB++;

    // Move Up
    if(element == index) break;
    for ( int i = nbLine-1; i >= nbLineB ; i–, index++)
    {
    response.add(matrix[i][nbColB]);
    }

    nbColB++;

    }

    // Print
    for(Integer value : response)
    {
    System.out.print(value + ” “);
    }
    // Or return… ( don’t forget to change method signature )
    //return response;

  2. Well, technically it is a correct answer as it enumerates the matrix elements in a spiral order.
    It just starts the traversal down instead of to the right 🙂

    If you flip the assigned values on line 9:
    int sideLen = mx[0].length, nextSideLen = mx.length;
    and flip the indexes on line 18:
    result.add(mx[y][x]);
    I suppose this should fix the spiraling direction.

  3. For an input of { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, {9,10,11,12} } -> the output is [1, 5, 9, 10, 11, 12, 8, 4, 3, 2, 6, 7] instead of [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7], so basically the code is producing wrong output.

  4. Simplified solution with two major design improvements:
    1) no code duplication;
    2) traversal is done with one loop i.e. you can easily convert the function into iterator over the matrix cells;

    public static List getSpiralTraversal(int[][] mx) {
    List result = new ArrayList();

    // Set initial direction
    int dx = 1, dy = 0;
    // Set the starting point before the first mx cell
    int x = -1, y = 0;
    // Set the first side length and the next side length
    int sideLen = mx.length, nextSideLen = mx[0].length;
    int sideCounter = sideLen;
    // While both of the run lengths are non-zero
    while (sideLen > 0 && nextSideLen > 0) {
    if (sideCounter > 0) {
    // traverse the side while counter is > 0
    sideCounter--;
    x += dx;
    y += dy;
    result.add(mx[x][y]);
    } else {
    // switch direction when the counter is 0
    int tmp;
    // Switch the direction -> rotates the sequence (1,0) (0,1) (-1,0) (0,-1)
    tmp = dx; dx = -dy; dy = tmp;
    // Reduce the next run length with one and switch dimensions
    tmp = sideLen; sideLen = nextSideLen - 1; nextSideLen = tmp;
    // Reset the side run counter
    sideCounter = sideLen;
    }
    }

    return result;
    }

  5. I solved by a simple solution which has almost the same performance of solution 2 as follows:

    private static final int RIGHT_D = 1;
    private static final int DOWN_D = 2;
    private static final int LEFT_D = 3;
    private static final int UP_D = 4;

    private static Integer nextDir(Integer dir) {
    if (dir == null || dir == UP_D) {
    return RIGHT_D;
    } else if (dir == RIGHT_D) {
    return DOWN_D;
    } else if (dir == DOWN_D) {
    return LEFT_D;
    } else if (dir == LEFT_D) {
    return UP_D;
    }
    return null;
    }

    private static void moveCounters(Integer dir, int[][] arr) {
    switch (dir) {
    case RIGHT_D:
    if (currentC 0) {
    currentC–;
    } else {
    moveCounters(UP_D, arr);
    }
    break;
    case DOWN_D:
    if (currentR 0) {
    currentR–;
    } else {
    moveCounters(RIGHT_D, arr);
    }
    break;
    default:
    }
    }

    private static int currentC = 0;
    private static int currentR = 0;

    public static List getSpiralMatrix(int arr[][]) {
    if (arr == null) {
    return null;
    }

    List output = new LinkedList();
    if (arr[0].length == 1 && arr.length == 1) {
    output.add(arr[0][0]);
    return output;
    }

    Integer dir = null;
    int visitedC = 0;
    int visitedR = 0;
    int nextTurnCounter = 0;
    int noOfRows = arr.length;

    int noOfCols = arr[0].length;

    while (output.size() < noOfCols * noOfRows) {
    dir = nextDir(dir);
    if (dir == RIGHT_D || dir == LEFT_D) {
    nextTurnCounter = noOfCols – visitedC;
    } else {
    nextTurnCounter = noOfRows – visitedR;
    }
    for (int i = 0; i < nextTurnCounter; i++) {
    output.add(arr[currentR][currentC]);
    moveCounters(dir, arr);
    }
    if (dir == RIGHT_D || dir == LEFT_D) {
    visitedR++;
    } else {
    visitedC++;
    }
    }

    return output;

    }

  6. I am sharing this code which I designed for a different purpose; it is about finding the Column number “X”, and the row number “Y” of array element @ spiral index “index”. Of course, this function can be used to produce the same required output. I think it is the fastest possible method (as it jumps over cells instead of scanning them), and it

    rec BuildSpiralIndex(long w, long h, long index = -1)
    {
    long count = 0 , x = -1, y = -1, dir = 1, phase=0, pos = 0, length = 0, totallength = 0;
    bool isVertical = false;
    if(index>=(w*h)) return null;

    do
    {
    isVertical = (count % 2) != 0;
    length = (isVertical ? h : w) – count/2 – count%2 ;
    totallength += length;
    count++;
    } while(totallength 1 ? phase : w – phase);
    y = ((pos == 1 || pos == 2) ? h – phase : phase) + (1 * (pos == 3 ? 1 : 0));
    dir = pos > 1 ? -1 : 1;
    if (isVertical) y -= (totallength – index – 1) * dir;
    else x -= (totallength – index -1) * dir;
    return new rec { X = x, Y = y };
    }

  7. Thank you for your solutions.

    But, I do believe that your recursive Solution #2 can be simplified a little. There are some checks in place that I think are unnecessary. I am posting my private helper function. I have unit-tested my solution using matrices of various sizes starting from 1×1 up to 5×4

    private List spiral(final int[][] matrix, int currentRow, int currentCol, int rows, int cols) {
    final List result = new ArrayList();
    if (rows <= 0 || cols <= 0) {
    return result;
    }

    //only one element left
    if (rows == 1 && cols == 1) {
    result.add(matrix[currentRow][currentCol]);
    return result;
    }

    //Top side: Move from left to right
    for (int idx = 0; idx < cols - 1 /* the '-1' is important, it will be the start of next loop */; idx++) {
    result.add(matrix[currentRow][currentCol++]);
    }

    //Right side: Move from top to bottom
    for (int idx = 0; idx < rows - 1 /* the '-1' is important*/; idx++) {
    result.add(matrix[currentRow++][currentCol]);
    }

    //Bottom side: Move from right to left
    for (int idx = 0; idx < cols - 1 /* the '-1' is important*/; idx++) {
    result.add(matrix[currentRow][currentCol--]);
    }

    //Left side: Move from bottom to top
    for (int idx = 0; idx < rows - 1 /* the '-1' is important*/; idx++) {
    result.add(matrix[currentRow--][currentCol]);
    }

    // By the time we reached here, we finished walking the external 'circle',
    // the currentRow & currentCol are back to zeroes.
    //
    // Now, we want to start walking the next inner circle, by incrementing
    // currentRow & currentCol and adjusting the matrix limits
    result.addAll(spiral(matrix, currentRow + 1, currentCol + 1, rows - 2, cols - 2));
    return result;
    }

  8. Hi
    i just want to share my solution. I think it is more simple.

    public static void spiralPrint(int arr[][]){

    int m = arr.length;

    int n = arr[0].length;

    int i = 0;

    int srow = 0; int erow = m – 1;

    int scol = 0; int ecol = n – 1;

    while(i < m*n){

    for (int j = scol; j <= ecol; j++) {

    System.out.print(arr[srow][j] + " ");

    i++;

    }

    srow++;

    for (int j = srow; j = scol; j–) {

    System.out.print(arr[erow][j] + ” “);

    i++;

    }

    erow–;

    for (int j = erow; j >= srow; j–) {

    System.out.print(arr[j][scol] + ” “);

    i++;

    }

    scol++;

    }

    }

    I will be happy to get a feedback.
    Thanks

  9. Just want to share a Python solution since it’s extremely simple:

    def spiral_matrix(m):
    result = []
    while len(m) > 0:
    result += m[0]
    m = zip(*m[1:len(m)])[::-1]
    return result

  10. I reversed the for-loop increment after every row increment

    public class Solution {
    public ArrayList sprialOrder(int[][] matrix) {
    ArrayList result = new ArrayList();
    int row = matrix.length;
    int col = matrix[0].length;
    int rowIdx = 0;

    while (result.size() < (row * col)) {
    for (int colIdx = 0; colIdx = (row * col)) {
    break;
    }

    rowIdx++; //down row

    for (int colIdx = (col – 1); colIdx >= 0; colIdx–) {
    result.add(matrix[rowIdx][colIdx]);
    }

    if (result.size() >= (row * col)) {
    break;
    }
    rowIdx++; //down row
    }
    return result;
    }
    }

  11. This is will provide the same functionality with complexity of O(m*n) where m and n are size of row and column

    private static List spiralMatrix(int arr[][], int m, int n) {
    List result = new ArrayList();
    if (m <= 0 || n <= 0)
    return result;
    int i = 0, j = 0, m1 = 0, n1 = 0, m2 = m – 1, n2 = n – 1, flag = 0;
    while (true) {
    result.add(arr[i][j]);
    if (flag == 0 && j == n2) {
    m1++;
    flag = (flag + 1) % 4;
    } else if (flag == 1 && i == m2) {
    n2–;
    flag = (flag + 1) % 4;
    } else if (flag == 2 && j == n1) {
    m2–;
    flag = (flag + 1) % 4;
    } else if (flag == 3 && i == m1) {
    n1++;
    flag = (flag + 1) % 4;
    }

    if (flag == 0) {
    j++;
    } else if (flag == 1) {
    i++;
    } else if (flag == 2) {
    j–;
    } else if (flag == 3) {
    i–;
    }

    if (i m2 || j n2) {
    break;
    }

    }
    return result;
    }

  12. This might be a little bit more concise, do not need to check if only one column or row left. already pass all tests.

    public List spiralOrder(int[][] matrix) {

    if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {

    return new ArrayList();

    }

    List result = new ArrayList();

    int width = matrix[0].length, height = matrix.length, count = width * height, layer = 0;

    while (count > 0) {

    // top

    for (int i = layer; count > 0 && i 0 && i 0 && i >= layer; i–) {

    result.add(matrix[height – layer – 1][i]);

    count –;

    }

    // left

    for (int i = height – layer – 2; count > 0 && i > layer; i–) {

    result.add(matrix[i][layer]);

    count –;

    }

    layer ++;

    }

    return result;

    }

  13. Thank you for all these great algorithm solutions. I found the solutions you provided are really clear and short compared to other places. Keep posting it up.

Leave a Comment