Problem Statement
We’re given a grid of numbers (an m x n integer matrix). Our mission is to take a specific square portion of this grid, defined by its top-left corner (x, y) and its side length k, and flip it upside down. Essentially, we need to reverse the order of the rows within that square submatrix. We then return the modified grid.
Breaking Down the Problem
At its heart, this problem asks us to manipulate a specific section of a 2D array. The key operation is reversing the order of rows within that designated square. We need to be careful not to affect the parts of the grid outside this submatrix.
The main challenge lies in correctly identifying the rows that belong to the submatrix and then performing the reversal on only those rows, while maintaining the order of elements within each row.
A potential hidden constraint is that the submatrix is always a square. This might simplify some approaches compared to dealing with a rectangular submatrix.
Intuition & Thought Process
Imagine your matrix is a multi-level bookshelf. You are asked to reverse the order of a specific section of books on a few shelves.
xandytell you which shelf and which position on the shelf to start at.ktells you how many shelves deep and how many books across your section is.
Your task is to flip this block of books “vertically.” How would you do it efficiently? You wouldn’t create a whole new bookshelf section. Instead, you’d perform the swaps directly on the existing shelf.
You would take the entire top row of books in your section and swap their position with the entire bottom row of books. Then, you’d take the second shelf from the top and swap it with the second from the bottom. You would continue this process, working from the outside in, until you reach the middle.
This bookshelf analogy is a perfect fit for our problem. Each row in the submatrix is like a shelf of books. Our goal is to swap the entire top “shelf” (row) with the bottom “shelf” (row), then the next pair, and so on, until the whole section is reversed.
A brute-force approach might involve taking all the books in the section off the shelf, arranging them in the flipped order on a temporary cart, and then putting them back. While this works, it requires extra space (the cart) and is less efficient. We can do better by swapping the rows directly on the “bookshelf” (the grid).
Step-by-Step Approach
This problem falls into the category of array manipulation. The efficient approach involves using a two-pointer technique.
- Identify the Row Range: Determine the starting and ending row indices of the submatrix we need to flip. These will be
start_row = xandend_row = x + k - 1. - Initialize Pointers: Set up two pointers, one at the beginning of the submatrix rows (
top = start_row) and one at the end (bottom = end_row). - Iterate and Swap: While
topis less thanbottom, we need to swap the row at index top with the row at index bottom. Since we are dealing with rows within a 2D array, we need to swap the entire row. - Move Pointers: After swapping, increment
topand decrementbottomto move towards the middle of the submatrix rows. - Repeat: Continue this process until
topis no longer less thanbottom. At this point, the rows within the submatrix will be reversed.
Time & Space Complexity
Brute-Force (with temporary matrix):
- Time Complexity: O(k²) to copy the submatrix to the temporary matrix and then back.
- Space Complexity: O(k²) to store the temporary submatrix.
Optimized (two-pointer):
- Time Complexity: O(k²) because in the worst case, we iterate through all
krows of the submatrix, and for each swap, we potentially iterate throughkelements in those rows. - Space Complexity: O(1) as we are modifying the grid in place using a constant amount of extra space for the pointers.
Code Implementation
Here are the optimized, in-place solutions in C++, Java, Python, and JavaScript.
C++
#include <vector>
#include <algorithm> // Required for std::swap
class Solution {
public:
// The function modifies the grid in-place and returns it.
std::vector<std::vector<int>>& flipSubmatrix(std::vector<std::vector<int>>& grid, int x, int y, int k) {
int top = x;
int bottom = x + k - 1;
// Loop until the top and bottom pointers meet or cross.
while (top < bottom) {
// For the current pair of rows, iterate through the columns of the submatrix.
for (int j = y; j < y + k; ++j) {
// Swap the elements at the same column index in the top and bottom rows.
std::swap(grid[top][j], grid[bottom][j]);
}
// Move the pointers towards the center.
top++;
bottom--;
}
return grid;
}
};Java
class Solution {
public int[][] flipSubmatrix(int[][] grid, int x, int y, int k) {
int top = x;
int bottom = x + k - 1;
// Loop until the top and bottom pointers meet in the middle.
while (top < bottom) {
// Iterate through the columns of the submatrix for the current rows.
for (int j = y; j < y + k; j++) {
// A classic swap using a temporary variable.
int temp = grid[top][j];
grid[top][j] = grid[bottom][j];
grid[bottom][j] = temp;
}
// Move pointers inward for the next pair of rows.
top++;
bottom--;
}
return grid;
}
}Python
from typing import List
class Solution:
def flipSubmatrix(self, grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
top = x
bottom = x + k - 1
# Continue swapping rows until the pointers meet.
while top < bottom:
# In Python, we can swap the entire relevant slice of the rows directly.
# This is more efficient and concise than a manual for-loop swap.
grid[top][y:y+k], grid[bottom][y:y+k] = grid[bottom][y:y+k], grid[top][y:y+k]
# Move the pointers towards each other.
top += 1
bottom -= 1
return gridJavaScript
/**
* @param {number[][]} grid
* @param {number} x
* @param {number} y
* @param {number} k
* @return {number[][]}
*/
var flipSubmatrix = function(grid, x, y, k) {
let top = x;
let bottom = x + k - 1;
// Loop from the outside rows of the submatrix inwards.
while (top < bottom) {
// Iterate through the columns of the submatrix.
for (let j = y; j < y + k; j++) {
// Use array destructuring for a clean, inline swap.
[grid[top][j], grid[bottom][j]] = [grid[bottom][j], grid[top][j]];
}
// Move the pointers to the next inner pair of rows.
top++;
bottom--;
}
return grid;
};How to Recognize Similar Problems
Problems involving in-place reversal or manipulation of a specific segment of an array or matrix often hint at the use of two-pointer techniques. Look out for keywords like “reverse a sublist,” “rotate a section,” or any task that requires modifying a contiguous part of a data structure.