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;
    }
}
Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • Ahmed Moharram

    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 };
    }

  • Alexander Zagniotov

    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;
    }

  • Kyle

    Solution 1 is very neat and easy to understand. Thanks.

  • Dado

    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

  • Yuval Carmel

    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

  • Brian Batchelor

    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;
    }
    }

  • Sureshkumar T

    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;
    }

  • Kirk Qin

    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;

    }

  • Yuqing Chen

    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.