Spiral Matrix Traversal: From Outer to Inner

Problem Analysis

The spiral matrix traversal problem requires printing matrix elements in a clockwise spiral pattern, starting from the top-left corner and moving inward layer by layer. The traversal follows a consistent pattern: move right along the top edge, then down the right edge, then left along the bottom edge, and finally up the left edge before transitioning to the next inner layer.

Solution Approaches

Direction-Based Traevrsal

This approach uses a direction matrix to control movement and a visited array to track traversed positions.

function spiralTraverse(matrix) {
    if (!matrix || matrix.length === 0) {
        return [];
    }
    
    const numRows = matrix.length;
    const numCols = matrix[0].length;
    const visited = Array.from({ length: numRows }, () => new Array(numCols).fill(false));
    const result = new Array(numRows * numCols);
    
    const dirX = [0, 1, 0, -1];
    const dirY = [1, 0, -1, 0];
    
    let currentDir = 0;
    let x = 0, y = 0;
    
    for (let i = 0; i < result.length; i++) {
        result[i] = matrix[x][y];
        visited[x][y] = true;
        
        const nextX = x + dirX[currentDir];
        const nextY = y + dirY[currentDir];
        
        if (nextX < 0 || nextX >= numRows || nextY < 0 || nextY >= numCols || visited[nextX][nextY]) {
            currentDir = (currentDir + 1) % 4;
        }
        
        x += dirX[currentDir];
        y += dirY[currentDir];
    }
    
    return result;
}

The core mechanism relies on four direction vectors. When the next position is either out of bounds or already visited, the direction switches to the next one in sequence. This ensures automatic boundary handling without explicit edge-case management.

Boundary-Based Traversal

This method uses four boundary pointers to define the currrent spiral layer.

function spiralTraverse(matrix) {
    if (!matrix || matrix.length === 0) {
        return [];
    }
    
    const rows = matrix.length;
    const cols = matrix[0].length;
    const result = [];
    
    let left = 0, right = cols - 1;
    let top = 0, bottom = rows - 1;
    
    while (left <= right && top <= bottom) {
        // Traverse right along the top row
        for (let col = left; col <= right; col++) {
            result.push(matrix[top][col]);
        }
        
        // Traverse down along the right column
        for (let row = top + 1; row <= bottom; row++) {
            result.push(matrix[row][right]);
        }
        
        // Handle middle layers: traverse left along the bottom row
        if (left < right && top < bottom) {
            for (let col = right - 1; col > left; col--) {
                result.push(matrix[bottom][col]);
            }
            
            for (let row = bottom; row > top; row--) {
                result.push(matrix[row][left]);
            }
        }
        
        // Shrink boundaries for the next layer
        left++;
        right--;
        top++;
        bottom--;
    }
    
    return result;
}

The boundary pointers shrink inward after completing each layer. The conditional check prevents duplicate printing when the matrix has only one row or one column remaining.

Java Implementation

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return new int[0];
        }
        
        int rows = matrix.length;
        int cols = matrix[0].length;
        int[] result = new int[rows * cols];
        int pos = 0;
        
        int left = 0, right = cols - 1;
        int top = 0, bottom = rows - 1;
        
        while (left <= right && top <= bottom) {
            for (int c = left; c <= right; c++) {
                result[pos++] = matrix[top][c];
            }
            for (int r = top + 1; r <= bottom; r++) {
                result[pos++] = matrix[r][right];
            }
            
            if (left < right && top < bottom) {
                for (int c = right - 1; c > left; c--) {
                    result[pos++] = matrix[bottom][c];
                }
                for (int r = bottom; r > top; r--) {
                    result[pos++] = matrix[r][left];
                }
            }
            
            left++;
            right--;
            top++;
            bottom--;
        }
        
        return result;
    }
}

Complexity Analysis

Both approaches traverse each matrix element exactly once, resulting in O(m × n) time complexity where m represents rows and n represents columns. The direction-based method uses an additional visited array of the same size, while the boundary-based method only uses O(1) extra space besides the result array.

Key Considerations

The boundary-based approach requires careful handling of edge cases where rows or columns equal one. The direction-based approach handles these naturally through its boundary checking mechanism but incurs the memory cost of a visited array. Choosing between them depends on whether memory optimization or conceptual simplicity is prioritized for the specific use case.

Tags: matrix spiral-traversal array simulation boundary-iteration

Posted on Sat, 27 Jun 2026 17:49:40 +0000 by InfinityRogue