Medium · 2D arrays

Matrix Transpose

You already summed a matrix. Transposing it asks a sharper question: when you write a[i][j], are you sure about which of i and j means what?

At a glancePrint column j of the input as row j of the output — the loops swap places, with the outer loop over columns and the inner over rows.

Problem

Input: The first line holds two integers n and m (1 ≤ n, m ≤ 50) — the number of rows and columns. The next n lines each hold m integers.

Output: The transpose: m lines, each with n integers. Row j of the output is column j of the input.

Samples:

InputOutput
2 3
1 2 3
4 5 6
1 4
2 5
3 6
1 1
7
7
3 1
1
2
3
1 2 3

Notice the shape changes: a 2×3 matrix becomes 3×2. So the two loops that print the answer have swapped bounds — that's the whole trick, and the whole trap.

Your solution

main.cpp — your solution
Custom input for "Run my input"

Judging runs in your browser against hidden tests. A runaway loop is cut off after 3 seconds — still, make sure every loop has an exit. Your code is saved in this browser as you type.

Stuck? Hints

Hint 1 — You don't need a second array

The obvious approach is to build b[m][n] with b[j][i] = a[i][j] and then print it. That works, but you can print directly: reading the matrix in row order and printing it in column order is the transpose. One array, zero copies.

Hint 2 — Swap the loop bounds, not just the indices

The outer loop runs j from 0 to m - 1, the inner runs i from 0 to n - 1. Writing a[j][i] while keeping the bounds at n and m reads out of bounds the moment the matrix isn't square — and for a square matrix it silently prints the original.

Hint 3 — Say the indices out loud

a[row][column] — the first index is always the row, in C++ and in every language that uses this notation. Before writing any nested loop over a grid, say which loop variable is the row and which is the column. Most 2D-array bugs are not logic errors; they are a swap you didn't notice.

Solution (try it first!)
#include <iostream>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    int a[55][55];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];

    for (int j = 0; j < m; j++) {
        for (int i = 0; i < n; i++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

Transposing without a second array works because you never needed the transpose to exist — you only needed to read the data in a different order. That distinction, "do I need to rearrange the data, or just traverse it differently?", saves you a copy in a lot of problems. Rotating a matrix 90°, multiplying two matrices, and walking a grid's diagonals are all variations on this. Next: a problem where the data is a number written in a base you choose — Base Conversion.

Deep dive

Why this works

Reading the matrix in row order and printing it in column order *is* the transpose. You never needed the transpose to exist — only to be traversed differently.

The cost

O(n×m) time and zero extra space. Building a second matrix and printing that costs an extra n×m block for nothing.

Where it goes wrong

  • Swapping to a[j][i] while keeping the loop bounds at n and m reads out of bounds whenever the matrix isn't square — and for a square matrix it silently prints the original.
  • In a[row][column] the first index is always the row. Say out loud which loop variable is which before writing any nested loop over a grid.

Next step

Now the data is a number written in a base you choose: Base Conversion.

Two things to remember

  • Read by rows, print by columns — that's the transpose.
  • a[row][column]: the first index is always the row.
🐞 This version fails — open it and try

Prints the matrix as-is — the transpose never happened

#include <iostream>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    int a[55][55];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) cout << a[i][j] << " ";
        cout << endl;
    }
    return 0;
}