Spiral Matrix

Problem

Given an m x n matrix of integers matrix, return a list of all elements within the matrix in spiral order.

Examples

Example 1:

Input: matrix = [[1,2],[3,4]]

Output: [1,2,4,3]

Example 2:

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

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

Example 3:

Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]

Output: [1,2,3,4,8,12,11,10,9,5,6,7]

Constraints

  • 1 <= matrix.length, matrix[i].length <= 10
  • -100 <= matrix[i][j] <= 100

You should aim for a solution with O(m*n) time and O(1) extra space, where m is the number of rows and n is the number of columns in the given matrix.

Solution

Use an outer loop over how many layers we have to do, then an inner 4 loops over top row, right col (minus top row element), bottom row (minus far right col element), then left col (minus bottom and top element). For an odd number of rows/cols, then the top and right sweeps will cover everything, and doing a bottom/left will duplicate. So we check in the middle.

class Solution {
    constexpr auto ceil_div(int num, int denom) {
        return (num + denom - 1) / denom;
    }
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        const int M = matrix.size();
        const int N = matrix[0].size();
        const int L = std::min(ceil_div(M, 2), ceil_div(N, 2));
 
        std::vector<int> result;
        for (int l = 0; l < L; ++l) {
            int top = l;
            int bottom = M - l - 1;
            int left = l;
            int right = N - l - 1;
 
            // Walk along the top row
            for (int c = left; c <= right; ++c) {
                result.push_back(matrix[top][c]);
            }
 
            // Walk along the right column
            for (int r = top + 1; r <= bottom; ++r) {
                result.push_back(matrix[r][right]);
            }
 
            // If there is no separate bottom row or no separate left column,
            // then bottom/left would duplicate cells we already visited.
            if (!(top < bottom && left < right)) {
                break;
            }
 
            // Walk along the bottom row
            for (int c = right - 1; c >= left; --c) {
                result.push_back(matrix[bottom][c]);
            }
 
            // Walk along the left column
            for (int r = bottom - 1; r >= top + 1; --r) {
                result.push_back(matrix[r][left]);
            }
        }
        return result;
    }
};