Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Matrix Traversal
DSA

Matrix Traversal

Learn systematic techniques for traversing matrices by rows, columns, diagonals, and directions.

Matrix Traversal visits every cell of a 2D matrix in a specific order.

Focus on recognizing:

2D Grid + Specific Order → Matrix Traversal


Pattern Table

PatternKeywords / Detection CuesMain Idea
Row-wiserow-wise, left to rightRow outer, column inner
Column-wisecolumn-wise, top to bottomColumn outer, row inner
DiagonaldiagonalSame row + col
Zigzagdiagonal zigzagReverse direction every diagonal
Boundaryboundary, perimeterTraverse edges

Row-Wise Traversal

Watch the zigzag sweep [1..9] diagonal by diagonal — direction flips each stripe. Press to animate.

Diagonal (Zigzag) Traversal

Visit every cell of a matrix by walking its anti-diagonals (cells sharing the same row+col), alternating direction each diagonal — the classic zigzag order.

Matrix: [[1,2,3],[4,5,6],[7,8,9]]. Diagonal 0 (sum row+col=0): (0,0). Diagonal 1: (0,1),(1,0). Diagonal 2: (2,0),(1,1),(0,2). Direction alternates each diagonal. The highlighted cells are the current diagonal.

GRID VISUALIZER
Steps
1
2
3
4
5
6
7
8
9
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        for sum in 0..rows+cols-2:
                      
                        2
                          if sum even: walk bottom→top on this diagonal
                      
                        3
                          else: walk top→bottom
                      
                        4
                          collect cells where col = sum - row is in bounds
                      
                        5
                        output: 1 2 4 7 5 3 6 8 9
                      
public void rowWise(int[][] matrix) {
    for (int row = 0; row < matrix.length; row++) {
        for (int col = 0; col < matrix[0].length; col++) {
            System.out.print(matrix[row][col] + " ");
        }
    }
}
def row_wise(matrix):
    for row in matrix:
        for val in row:
            print(val, end=" ")
void rowWise(vector<vector<int>>& matrix) {
    for (auto& row : matrix)
        for (int val : row)
            cout << val << " ";
}
function rowWise(matrix) {
  for (const row of matrix) {
    for (const val of row) {
      process.stdout.write(`${val} `);
    }
  }
}

Output for [1..9] grid: 1 2 3 4 5 6 7 8 9.


Column-Wise Traversal

Swap the loops — columns outer, rows inner:

public void columnWise(int[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[0].length;

    for (int col = 0; col < cols; col++) {
        for (int row = 0; row < rows; row++) {
            System.out.print(matrix[row][col] + " ");
        }
    }
}
def column_wise(matrix):
    for col in range(len(matrix[0])):
        for row in range(len(matrix)):
            print(matrix[row][col], end=" ")
void columnWise(vector<vector<int>>& matrix) {
    int rows = matrix.size(), cols = matrix[0].size();

    for (int col = 0; col < cols; col++)
        for (int row = 0; row < rows; row++)
            cout << matrix[row][col] << " ";
}
function columnWise(matrix) {
  const rows = matrix.length,
    cols = matrix[0].length;

  for (let col = 0; col < cols; col++) {
    for (let row = 0; row < rows; row++) {
      process.stdout.write(`${matrix[row][col]} `);
    }
  }
}

Output: 1 4 7 2 5 8 3 6 9.


Diagonal Traversal

Cells on one anti-diagonal share row + col:

public List<Integer> diagonalTraversal(int[][] matrix) {
    List<Integer> result = new ArrayList<>();
    int rows = matrix.length;
    int cols = matrix[0].length;

    for (int sum = 0; sum < rows + cols - 1; sum++) {
        for (int row = 0; row < rows; row++) {
            int col = sum - row;

            if (col >= 0 && col < cols) {
                result.add(matrix[row][col]);
            }
        }
    }

    return result;
}
def diagonal_traversal(matrix):
    rows, cols = len(matrix), len(matrix[0])
    result = []

    for s in range(rows + cols - 1):
        for row in range(rows):
            col = s - row

            if 0 <= col < cols:
                result.append(matrix[row][col])

    return result
vector<int> diagonalTraversal(vector<vector<int>>& matrix) {
    int rows = matrix.size(), cols = matrix[0].size();
    vector<int> result;

    for (int sum = 0; sum < rows + cols - 1; sum++) {
        for (int row = 0; row < rows; row++) {
            int col = sum - row;

            if (col >= 0 && col < cols)
                result.push_back(matrix[row][col]);
        }
    }

    return result;
}
function diagonalTraversal(matrix) {
  const rows = matrix.length,
    cols = matrix[0].length;
  const result = [];

  for (let sum = 0; sum < rows + cols - 1; sum++) {
    for (let row = 0; row < rows; row++) {
      const col = sum - row;

      if (col >= 0 && col < cols) result.push(matrix[row][col]);
    }
  }

  return result;
}

Main diagonal → row − col constant · Anti-diagonal → row + col constant. Know both.


Zigzag Diagonal Traversal

Same grouping, but alternate direction per diagonal:

public int[] diagonalZigzag(int[][] matrix) {
    int rows = matrix.length, cols = matrix[0].length;
    int[] result = new int[rows * cols];
    int index = 0;

    for (int sum = 0; sum < rows + cols - 1; sum++) {

        if (sum % 2 == 0) {                       // bottom → top
            int row = Math.min(sum, rows - 1);

            while (row >= 0) {
                int col = sum - row;

                if (col >= 0 && col < cols)
                    result[index++] = matrix[row][col];
                row--;
            }
        } else {                                  // top → bottom
            int row = Math.max(0, sum - cols + 1);

            while (row < rows) {
                int col = sum - row;

                if (col >= 0 && col < cols)
                    result[index++] = matrix[row][col];
                row++;
            }
        }
    }

    return result;
}
def diagonal_zigzag(matrix):
    rows, cols = len(matrix), len(matrix[0])
    result = []

    for s in range(rows + cols - 1):
        diag = []

        for row in range(rows):
            col = s - row

            if 0 <= col < cols:
                diag.append(matrix[row][col])

        if s % 2 == 0:
            diag.reverse()      # bottom → top
        result.extend(diag)

    return result
vector<int> diagonalZigzag(vector<vector<int>>& matrix) {
    int rows = matrix.size(), cols = matrix[0].size();
    vector<int> result;

    for (int sum = 0; sum < rows + cols - 1; sum++) {
        vector<int> diag;

        for (int row = 0; row < rows; row++) {
            int col = sum - row;

            if (col >= 0 && col < cols)
                diag.push_back(matrix[row][col]);
        }

        if (sum % 2 == 0)
            reverse(diag.begin(), diag.end());   // bottom → top

        result.insert(result.end(), diag.begin(), diag.end());
    }

    return result;
}
function diagonalZigzag(matrix) {
  const rows = matrix.length,
    cols = matrix[0].length;
  const result = [];

  for (let sum = 0; sum < rows + cols - 1; sum++) {
    const diag = [];

    for (let row = 0; row < rows; row++) {
      const col = sum - row;

      if (col >= 0 && col < cols) diag.push(matrix[row][col]);
    }

    if (sum % 2 === 0) diag.reverse(); // bottom → top
    result.push(...diag);
  }

  return result;
}


Boundary Traversal

Four edges in order — top row, right column, bottom row, left column:

public List<Integer> boundaryTraversal(int[][] matrix) {
    List<Integer> result = new ArrayList<>();
    int rows = matrix.length, cols = matrix[0].length;

    for (int col = 0; col < cols; col++)              // top
        result.add(matrix[0][col]);

    for (int row = 1; row < rows; row++)              // right
        result.add(matrix[row][cols - 1]);

    if (rows > 1)
        for (int col = cols - 2; col >= 0; col--)     // bottom
            result.add(matrix[rows - 1][col]);

    if (cols > 1)
        for (int row = rows - 2; row > 0; row--)      // left
            result.add(matrix[row][0]);

    return result;
}
def boundary_traversal(matrix):
    rows, cols = len(matrix), len(matrix[0])
    result = []

    result.extend(matrix[0])                          # top

    for row in range(1, rows):                        # right
        result.append(matrix[row][-1])

    if rows > 1:
        result.extend(matrix[-1][-2::-1])             # bottom

    if cols > 1:
        for row in range(rows - 2, 0, -1):            # left
            result.append(matrix[row][0])

    return result
vector<int> boundaryTraversal(vector<vector<int>>& matrix) {
    int rows = matrix.size(), cols = matrix[0].size();
    vector<int> result;

    for (int col = 0; col < cols; col++)              // top
        result.push_back(matrix[0][col]);

    for (int row = 1; row < rows; row++)              // right
        result.push_back(matrix[row][cols - 1]);

    if (rows > 1)
        for (int col = cols - 2; col >= 0; col--)     // bottom
            result.push_back(matrix[rows - 1][col]);

    if (cols > 1)
        for (int row = rows - 2; row > 0; row--)      // left
            result.push_back(matrix[row][0]);

    return result;
}
function boundaryTraversal(matrix) {
  const rows = matrix.length,
    cols = matrix[0].length;
  const result = [...matrix[0]]; // top

  for (let row = 1; row < rows; row++) result.push(matrix[row][cols - 1]); // right

  if (rows > 1)
    for (let col = cols - 2; col >= 0; col--)
      result.push(matrix[rows - 1][col]); // bottom

  if (cols > 1)
    for (let row = rows - 2; row > 0; row--) result.push(matrix[row][0]); // left

  return result;
}

The rows > 1 / cols > 1 guards prevent double-counting corners on thin matrices.


Common Mistakes

Mixing rows and columns.

matrix.length = rows · matrix[0].length = columns. Swapping them breaks rectangular matrices.


Assuming a square matrix.

2 × 4 is valid — keep rows and cols separate everywhere.


Diagonal bounds.

On each diagonal, check BOTH 0 <= row < rows AND 0 <= col < cols before touching the cell.


Duplicate corners in boundary walks.

Single-row or single-column matrices revisit corners unless guarded.


Complexity

TraversalTimeSpace (output)
Row/ColO(n·m)O(n·m)
Diagonal/ZigzagO(n·m)O(n·m)
BoundaryO(n+m)O(n+m)

My Private Notes

Notes are auto-saved locally to this device.