2026-01-12:垂直翻转子矩阵。用go语言,给你一个大小为 m × n 的整数矩阵 grid,和三个整数 x、y、k。x、y 指定了矩阵中一个 k × k 子方块的起始位置(左上角坐标),k 是该方块的边长。
现在要把这个子方块内部的行按上下顺序倒置(即第 1 行与第 k 行互换,第 2 行与第 k-1 行互换,依此类推),矩阵其余部分保持不变。
返回完成该操作后的矩阵。
m == grid.length。
n == grid[i].length。
1 <= m, n <= 50。
1 <= grid[i][j] <= 100。
0 <= x < m。
0 <= y < n。
1 <= k <= min(m - x, n - y)。
输入: grid = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], x = 1, y = 0, k = 3。
输出: [[1,2,3,4],[13,14,15,8],[9,10,11,12],[5,6,7,16]]。
解释:
上图展示了矩阵在变换前后的样子。
题目来自力扣3643。
执行过程分步解析
-
确定子方块边界: 程序首先根据传入的参数
x(起始行)、y(起始列)和k(子方块边长),计算出需要翻转的k×k子方块的精确范围。这个子方块的上边界是第x行,下边界是第x + k - 1行;左边界是第y列,右边界是第y + k - 1列。矩阵中在此区域之外的所有元素都保持不变。 -
初始化双指针: 为了对子方块的行进行垂直翻转(即上下颠倒),代码使用了两枚指针
l(左指针/上指针)和r(右指针/下指针)来协同工作。指针l初始化为子方块的首行x,指针r初始化为子方块的末行x + k - 1。 -
循环交换行: 核心操作在一个循环中完成,只要
l指针小于r指针,循环就继续。这个条件确保了只需遍历子方块上半部分的行,并与下半部分对应的行交换,从而高效完成翻转。- 遍历列元素:在每一次循环中,代码会遍历当前行
l和行r上,从列y到y + k - 1的所有元素。 - 对称交换:对于遍历到的每一列
j,代码将grid[l][j]的值与grid[r][j]的值进行交换。这一步实现了两整行数据的对调。 - 移动指针:完成一对行的交换后,
l指针向下移动一行(l++),r指针向上移动一行(r--),准备处理下一对需要交换的行。
- 遍历列元素:在每一次循环中,代码会遍历当前行
-
返回结果: 当所有需要交换的行对都处理完毕后,循环结束。此时,指定的子方块内部已经完成了垂直翻转,而矩阵的其他部分未被改动。函数最终返回修改后的
grid矩阵。
示例验证
以您提供的输入为例:
- 输入:
grid = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],x = 1,y = 0,k = 3 - 子方块范围:从第1行第0列开始,边长为3的子方块包含的行是1, 2, 3,即数值为
[5,6,7,8],[9,10,11,12],[13,14,15,16]的三行。 - 翻转过程:
- 交换第1行(
[5,6,7,8])和第3行([13,14,15,16])。 - 此时,第2行(
[9,10,11,12])位于中间,与自己交换(或无操作)。
- 交换第1行(
- 最终结果:子方块变为
[13,14,15,16],[9,10,11,12],[5,6,7,8],与矩阵未变动的前两行组合,得到输出[[1,2,3,4],[13,14,15,8],[9,10,11,12],[5,6,7,16]]。
复杂度分析
-
总的时间复杂度:O(k²)。 算法需要交换大约
k/2对行,对于每一对行,需要遍历k列元素进行交换。因此,总的操作次数与k * k成正比,即 O(k²)。 -
总的额外空间复杂度:O(1)。 算法直接在输入的
grid矩阵上进行元素交换操作,仅使用了固定数量的额外变量(如l,r,j以及交换时的临时空间),没有使用与输入数据规模相关的额外存储空间。
Go完整代码如下:
package main
import (
"fmt"
)
func reverseSubmatrix(grid [][]int, x, y, k int) [][]int {
l, r := x, x+k-1
for l < r {
for j := y; j < y+k; j++ {
grid[l][j], grid[r][j] = grid[r][j], grid[l][j]
}
l++
r--
}
return grid
}
func main() {
grid := [][]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}
x := 1
y := 0
k := 3
result := reverseSubmatrix(grid, x, y, k)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
from typing import List
def reverse_submatrix(grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
"""
反转指定子矩阵的行顺序
参数:
grid: 输入矩阵
x: 子矩阵左上角的行索引
y: 子矩阵左上角的列索引
k: 子矩阵的大小(k × k)
返回:
修改后的矩阵
"""
l, r = x, x + k - 1
while l < r:
# 交换第l行和第r行在子矩阵范围内的元素
for j in range(y, y + k):
grid[l][j], grid[r][j] = grid[r][j], grid[l][j]
l += 1
r -= 1
return grid
def main():
grid = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
x = 1
y = 0
k = 3
# 输出原始矩阵
print("原始矩阵:")
for row in grid:
print(row)
# 反转子矩阵
result = reverse_submatrix(grid, x, y, k)
# 输出结果矩阵
print("\n反转子矩阵后的结果:")
for row in result:
print(row)
if __name__ == "__main__":
main()
C++完整代码如下:
#include <iostream>
#include <vector>
using namespace std;
// 反转指定子矩阵的行顺序
vector<vector<int>> reverseSubmatrix(vector<vector<int>>& grid, int x, int y, int k) {
int l = x, r = x + k - 1;
while (l < r) {
// 交换第l行和第r行在子矩阵范围内的元素
for (int j = y; j < y + k; j++) {
swap(grid[l][j], grid[r][j]);
}
l++;
r--;
}
return grid;
}
// 打印矩阵的函数
void printMatrix(const vector<vector<int>>& grid) {
for (const auto& row : grid) {
cout << "[";
for (size_t i = 0; i < row.size(); i++) {
cout << row[i];
if (i != row.size() - 1) {
cout << ", ";
}
}
cout << "]" << endl;
}
}
int main() {
// 初始化4x4矩阵
vector<vector<int>> grid = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}
};
int x = 1;
int y = 0;
int k = 3;
// 输出原始矩阵
cout << "原始矩阵:" << endl;
printMatrix(grid);
// 反转子矩阵
vector<vector<int>> result = reverseSubmatrix(grid, x, y, k);
// 输出结果矩阵
cout << "\n反转子矩阵后的结果:" << endl;
printMatrix(result);
return 0;
}