Spiral Order of a Matrix

medium Matrix (2D arrays)

Problem

Read a matrix. Print all its elements in spiral order: go right along the top row, down the right column, left along the bottom row, up the left column, and then continue inside.

Constraints

  • 1 <= r, c <= 100

Examples

Input

3 3
1 2 3
4 5 6
7 8 9

Output

1 2 3 6 9 8 7 4 5

Solutions

Best approachTime O(r * c)Space O(r * c)

We keep four borders around the unvisited part. After walking one side, we move that border inward. The two checks in steps 4 and 5 protect single rows and single columns from being visited twice.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process a matrix.
 * Input   : r and c, then r rows of c integers.
 * Output  : Elements in spiral order.
 * Approach: Shrink four borders.
 * Time    : O(r * c)
 * Space   : O(r * c)
 * Java    : 8 or newer.
 */
import java.util.Scanner;
import java.util.Arrays;
import java.util.stream.Collectors;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static int[] solve(int[][] m) {
        int rows = m.length;
        int cols = m[0].length;
        int[] result = new int[rows * cols];
        int index = 0;

        // Step 1: The four borders of the part that is not visited yet.
        int top = 0;
        int bottom = rows - 1;
        int left = 0;
        int right = cols - 1;

        while (top <= bottom && left <= right) {
            // Step 2: Go right along the top row, then move the top border down.
            for (int j = left; j <= right; j++) {
                result[index++] = m[top][j];
            }
            top++;

            // Step 3: Go down along the right column, then move the right border left.
            for (int i = top; i <= bottom; i++) {
                result[index++] = m[i][right];
            }
            right--;

            // Step 4: Go left along the bottom row (only if a row is left), then move the bottom border up.
            if (top <= bottom) {
                for (int j = right; j >= left; j--) {
                    result[index++] = m[bottom][j];
                }
                bottom--;
            }

            // Step 5: Go up along the left column (only if a column is left), then move the left border right.
            if (left <= right) {
                for (int i = bottom; i >= top; i--) {
                    result[index++] = m[i][left];
                }
                left++;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int rows = scanner.nextInt();
        int cols = scanner.nextInt();
        int[][] m = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                m[i][j] = scanner.nextInt();
            }
        }
        System.out.println(Arrays.stream(solve(m)).mapToObj(String::valueOf).collect(Collectors.joining(" ")));
    }
}
Hints (1)
  1. Why must we check top <= bottom before the third side?