Skip to content
DSA arrays 8 min read

2D Arrays & Matrices: Grids, Rows, and Columns

A 2D array (or matrix) is a grid of values addressed by two indices — a row and a column — written m[row][col]. It’s the natural shape for tables, images, game boards, and adjacency matrices. Conceptually it’s a rectangle of rows × cols cells; physically most languages store it as an “array of arrays” or one flat block, but you index it the same way. This page covers creating a matrix and traversing it by row and by column.

Creating a matrix

Here is a 3×4 grid (3 rows, 4 columns) initialized to zero:

#include <vector>
int rows = 3, cols = 4;
std::vector<std::vector<int>> m(rows, std::vector<int>(cols, 0));
m[0][1] = 7;   // row 0, column 1

Pitfall: In Python, [[0] * cols] * rows creates rows references to the same inner list, so writing m[0][1] changes every row. Always build rows with a comprehension as above. The same aliasing trap exists in JavaScript if you reuse one inner array reference.

How a matrix is stored

Most languages use row-major order: each row is laid out contiguously, one after another. So m[r][c] lives at flat offset r * cols + c. Because rows are contiguous, scanning row by row is cache-friendly and fast; jumping column by column skips across memory and can be slower on large matrices.

Going deeper: Some languages and libraries (Fortran, some BLAS routines) use column-major order, where columns are contiguous instead. The access pattern that’s cheap simply flips. For everyday DSA in these four languages, assume row-major.

Row traversal

Visit every cell, row by row — the natural, cache-friendly order. This sums all elements:

long sumByRows(const std::vector<std::vector<int>>& m) {
    long total = 0;
    for (size_t r = 0; r < m.size(); r++)
        for (size_t c = 0; c < m[r].size(); c++)
            total += m[r][c];
    return total;
}

Column traversal

Sometimes you need to walk down each column — swap the loop order so the column index is the outer loop:

long sumByCols(const std::vector<std::vector<int>>& m) {
    long total = 0;
    int rows = m.size(), cols = rows ? m[0].size() : 0;
    for (int c = 0; c < cols; c++)
        for (int r = 0; r < rows; r++)
            total += m[r][c];
    return total;
}

Complexity

For an r × c matrix with n = r * c cells:

  • Access by m[i][j]: O(1)
  • Full traversal (any order): O(r · c) = O(n)
  • Space: O(r · c) to store the grid

Row and column traversal have the same Big-O; the difference is constant-factor cache performance, which favors the row-major order.

Where 2D arrays show up

Matrices power image grids, dynamic-programming tables (see DP on grids), and dense graph representations via adjacency matrices. Up next: array rotation and reversal, then practice on the array exercises.

Last updated June 25, 2026
Was this helpful?