Sweaty Imposter

Spiral Matrix

MediumMath & GeometryBlind 75MidOpen on LeetCodeUpdated

You're given an m x n matrix. Return all of its elements in spiral order: start at the top-left corner, move right along the top row, down the right column, left along the bottom row, and up the left column, then repeat on the remaining inner rectangle until every element is visited once.

Examples

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

519283764

The outer ring is read clockwise from 5 back up to 2, and then the single center cell 8 is all that remains.

matrix = [[2,4,6],[8,10,12]] returns [2,4,6,12,10,8]

With two rows, the walk goes right across the top and left across the bottom, and nothing is left inside.

matrix = [[7],[8],[9]] returns [7,8,9]

A single column is read straight down. No element may be visited twice on the way back up.

Constraints

  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

Hints

Hint 1

The spiral is a series of shrinking rectangles. What do you need to track to know which rectangle is left?

Hint 2
A pointer toward the approach
Hint 3
The full approach, step by step

Drill This: Your Approach First

Approach

Keep four boundaries, top, bottom, left, and right, for the rectangle still unread. Each lap reads the top row left to right and moves top down, then the right column top to bottom and moves right in. Before reading the bottom row right to left, check that top <= bottom, and before reading the left column bottom to top, check that left <= right, since a single leftover row or column would otherwise be read twice. Stop when the boundaries cross. O(m * n) time, O(1) extra space beyond the output.

Time

O(m * n)

Space

O(1) beyond the output

Pitfall

Skipping the two boundary checks in the middle of a lap. On a single row or column, the walk back reads the same cells again and the output has duplicates.

Solutions

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> out = new ArrayList<>();
        int top = 0, bottom = matrix.length - 1;
        int left = 0, right = matrix[0].length - 1;
        while (top <= bottom && left <= right) {
            for (int c = left; c <= right; c++) out.add(matrix[top][c]);
            top++;
            for (int r = top; r <= bottom; r++) out.add(matrix[r][right]);
            right--;
            if (top <= bottom) {
                for (int c = right; c >= left; c--) out.add(matrix[bottom][c]);
                bottom--;
            }
            if (left <= right) {
                for (int r = bottom; r >= top; r--) out.add(matrix[r][left]);
                left++;
            }
        }
        return out;
    }
}
Drill This