Matrix Makeover: Rotating Images 90 Degrees In-Place with C++
Hey LeetCoders and aspiring problem-solvers! 👋 Vansh2710 here, ready to demystify another classic LeetCode problem that might seem tricky at first glance, but unveils an elegant two-step solution. Today, we're diving into problem 48: Rotate Image.
Get ready to spin some matrices! 🔄
The Problem: Spin That Image!
You're given an n x n 2D matrix, which you can think of as a square image made of pixels (where each pixel has a numerical value). Your task is to rotate this "image" by 90 degrees clockwise.
Sounds simple, right? Here's the catch:
- You must do this rotation in-place. This means you can't create a brand new matrix, fill it with rotated values, and then return it. You have to modify the original matrix directly.
- DO NOT allocate another 2D matrix.
Let's look at an example to really nail down what we're aiming for:
Input:
matrix = [[1,2,3],
[4,5,6],
[7,8,9]]
Imagine this as:
1 2 3 <-- Top row
4 5 6
7 8 9 <-- Bottom row
Output:
[[7,4,1],
[8,5,2],
[9,6,3]]
After a 90-degree clockwise rotation, it should look like:
7 4 1
8 5 2
9 6 3
Notice how the 1 (top-left) moved to 3's old spot (top-right of the rotated matrix, which is bottom-right of the original), but it actually ends up in [0][2] position of the result. Wait, no, 1 from [0][0] moves to [0][2] in the output [[7,4,1],...]. Let's clarify the coordinate transformation for a moment:
- Original
(row, col)becomes(col, n - 1 - row)in the new matrix.-
1at(0,0)goes to(0, 3-1-0) = (0,2)in the output. Outputmatrix[0][2]is1. -
3at(0,2)goes to(2, 3-1-0) = (2,2)in the output. Outputmatrix[2][2]is3. -
7at(2,0)goes to(0, 3-1-2) = (0,0)in the output. Outputmatrix[0][0]is7.
-
This direct mapping approach is hard to do in-place without overwriting values you still need. So, what's the trick? 🤔
The Intuition: A Two-Step Dance!
The key to solving this problem efficiently and in-place lies in breaking down the complex 90-degree rotation into two simpler, sequential transformations. This is a classic trick for matrix manipulations!
Think about what happens when you rotate something 90 degrees clockwise:
- The rows become columns, and columns become rows. This sounds a lot like transposing a matrix.
- Then, the order within those new rows/columns seems reversed or mirrored.
Let's try this with our example: [[1,2,3],[4,5,6],[7,8,9]]
Step 1: Transpose the Matrix
Transposing means swapping matrix[i][j] with matrix[j][i]. It's like flipping the matrix along its main diagonal (top-left to bottom-right).
Original:
1 2 3
4 5 6
7 8 9
After Transposing (swapping (0,1) with (1,0), (0,2) with (2,0), (1,2) with (2,1)):
1 4 7
2 5 8
3 6 9
-
2and4swapped. -
3and7swapped. -
6and8swapped. -
1, 5, 9stayed in place (they are on the main diagonal).
Does this look like our desired output? Not yet! But we're closer. Notice the numbers are somewhat "lined up".
Step 2: Reverse Each Row
Now, let's take this transposed matrix and reverse the elements within each row.
Transposed Matrix:
1 4 7
2 5 8
3 6 9
Reverse Row 0 [1,4,7] -> [7,4,1]
Reverse Row 1 [2,5,8] -> [8,5,2]
Reverse Row 2 [3,6,9] -> [9,6,3]
Final Result:
7 4 1
8 5 2
9 6 3
Aha! This is exactly the output we wanted! 🎉
This two-step process – Transpose then Reverse Rows – is the elegant, in-place solution.
The Approach: Walking Through the Logic
Armed with our intuition, let's break down the exact steps to implement this:
Get the size: First, find the dimension
nof the square matrix.n = matrix.size().-
Transpose the Matrix:
- We need nested loops to iterate through the matrix elements.
- The outer loop
iwill go from0ton-1(for rows). - The inner loop
jwill go fromi+1ton-1(for columns). - Why
jstarts ati+1? To avoid two things:- Swapping an element with itself (
matrix[i][i]withmatrix[i][i]). - Swapping pairs twice (e.g., swapping
matrix[0][1]withmatrix[1][0], and then later swappingmatrix[1][0]withmatrix[0][1]again, which undoes the first swap). By startingjfromi+1, we only visit the "upper triangle" of the matrix, ensuring each unique pair is swapped exactly once.
- Swapping an element with itself (
- Inside the inner loop, perform the swap:
swap(matrix[i][j], matrix[j][i]).
-
Reverse Each Row:
- Now, we need another loop to iterate through each row of the matrix.
- The loop
iwill go from0ton-1. - For each row
matrix[i], use areversefunction (likestd::reversein C++) to reverse all its elements.
And that's it! Two simple loops, two clear operations, and your matrix is rotated!
The Code: Bringing it to Life
Here's the C++ implementation based on our approach:
#include <vector> // Required for std::vector
#include <algorithm> // Required for std::swap and std::reverse
class Solution {
public:
void rotate(std::vector<std::vector<int>>& matrix) {
int n = matrix.size(); // Get the dimension of the square matrix
// Step 1: Transpose the matrix
// Swap elements across the main diagonal (matrix[i][j] with matrix[j][i])
// We iterate through the upper triangle (j starts from i+1) to avoid redundant swaps
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
std::swap(matrix[i][j], matrix[j][i]);
}
}
// Step 2: Reverse each row
// After transposing, reversing each row completes the 90-degree clockwise rotation
for (int i = 0; i < n; ++i) {
std::reverse(matrix[i].begin(), matrix[i].end());
}
}
};
Complexity Analysis
Understanding how our solution scales with input size is crucial for competitive programming and good software design.
-
Time Complexity: O(n^2)
- The transposition step involves nested loops, where the outer loop runs
ntimes and the inner loop runs approximatelyn/2times on average (fromi+1ton-1). This results in roughly(n * (n-1))/2operations, which simplifies toO(n^2). - The row reversal step involves iterating through
nrows. For each row,std::reversetakesO(n)time (to reversenelements). So, this step is alson * O(n) = O(n^2). - Since both steps are
O(n^2), the dominant factor, the total time complexity isO(n^2). This is optimal because we have to visit every element in then x nmatrix at least once.
- The transposition step involves nested loops, where the outer loop runs
-
Space Complexity: O(1)
- We are modifying the matrix directly in-place. We don't use any additional data structures whose size depends on
n. -
std::swapandstd::reversemight use a small, constant amount of auxiliary space for temporary variables, but this is negligible in terms ofn. - Therefore, the auxiliary space complexity is
O(1). This meets the "DO NOT allocate another 2D matrix" constraint perfectly!
- We are modifying the matrix directly in-place. We don't use any additional data structures whose size depends on
Key Takeaways
- Decomposition is Powerful: Complex problems can often be broken down into simpler, sequential operations. For 90-degree clockwise matrix rotation, this is Transpose + Reverse Rows.
- In-place Transformations: Look for ways to manipulate data directly without extra memory. This often involves careful iteration patterns (like
j = i + 1for transposition) and using language-provided utilities (std::swap,std::reverse). - Visualize the Changes: Drawing out small examples and tracking element movement can lead to the "aha!" moment much faster.
This problem is a fantastic introduction to matrix manipulation and in-place algorithms. Understanding this pattern will help you tackle similar problems in the future!
Happy coding! ✨
Authored by Vansh2710.
Published on 2026-03-28 at 22:46:29.
Top comments (0)