【LetMeFly】1914.循环轮转矩阵:大模拟(数组原地轮转) ------ 附O(1)空间版本
力扣题目链接:https://leetcode.cn/problems/cyclically-rotating-a-grid/
给你一个大小为 m x n 的整数矩阵 grid ,其中 m 和 n 都是 偶数 ;另给你一个整数 k 。
矩阵由若干层组成,如下图所示,每种颜色代表一层:

矩阵的循环轮转是通过分别循环轮转矩阵中的每一层完成的。在对某一层进行一次循环旋转操作时,层中的每一个元素将会取代其 逆时针方向的相邻元素。轮转示例如下:

返回执行 k 次循环轮转操作后的矩阵。
示例 1:

输入:grid = [[40,10],[30,20]], k = 1
输出:[[10,20],[40,30]]
解释:上图展示了矩阵在执行循环轮转操作时每一步的状态。
示例 2:

输入:grid = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], k = 2
输出:[[3,4,8,12],[2,11,10,16],[1,7,6,15],[5,9,13,14]]
解释:上图展示了矩阵在执行循环轮转操作时每一步的状态。
提示:
m == grid.lengthn == grid[i].length2 <= m, n <= 50m和n都是 偶数1 <= grid[i][j] <=``50001 <= k <= 109
解题方法:大模拟
这道题目包含两个部分:
- 把矩阵拆成一圈一圈的(共计能拆 min { m , n } 2 \frac{\min \{m,n\}}2 2min{m,n}圈)、把一圈的数据写到一个数组中方便进行轮转处理,轮转完成后把数组写回矩阵的这一圈;
- 对于一个(上一部分拆分出来的)数组,轮转 k k k次。
对于1.的模拟部分,当我们处理到从外到内第 t h th th圈时,这一圈共有 ( m + n ) × 2 − 4 − 8 × t h (m + n) \times 2 - 4-8\times th (m+n)×2−4−8×th个元素(记为 a l l all all个元素)。创建一个长度为 a l l all all的数组,逆时针遍历这一圈并将数据放入临时一维数组中,待数组完成 k k k-轮转后再次遍历并放回原始矩阵。
对于2.的轮转部分,数组长度为 a l l all all,首先令 k k k对 a l l all all取模,接着把数组向左轮转 k k k次。由于 k < ( m + n ) × 2 − 4 k\lt (m+n)\times 2-4 k<(m+n)×2−4,所以直接模拟 k k k次也行(时间复杂度 O ( a l l × k ) O(all\times k) O(all×k));或者使用一个时间复杂度 O ( a l l ) O(all) O(all)空间复杂度 O ( 1 ) O(1) O(1)的方法更好(懂得原理后也会觉得更加简单):
1 , 2 , 3 , 4 , 5 , 6 , 7 \] \[1, 2, 3, 4, 5, 6, 7\] \[1,2,3,4,5,6,7\]如何向左轮转 3 3 3次变成 \[ 4 , 5 , 6 , 7 , 1 , 2 , 3 \] \[4,5,6,7,1,2,3\] \[4,5,6,7,1,2,3\]呢?三次翻转操作即可。 第一次翻转直接翻转整个数组,第二次翻转前 a l l − k all-k all−k个元素,第三次翻转后 k k k个元素就行了。是的,就这么简单。 1 2 3 4 5 6 7 ------------- ↓ 7 6 5 4 3 2 1 ------- ↓ 4 5 6 7 3 2 1 ----- ↓ 4 5 6 7 1 2 3
- 时间复杂度 O ( m n ) O(mn) O(mn)
- 空间复杂度 O ( m + n ) O(m+n) O(m+n),使用了一圈的临时空间
如果你是狠人的话(如ChatGPT),甚至能写个 O ( 1 ) O(1) O(1)空间的原地翻转,记得处理好下标映射就好了。
AC代码
C++
cpp
/*
* @LastEditTime: 2026-05-09 22:15:48
*/
class Solution {
private:
int n, m, k;
vector<vector<int>> grid;
void init(vector<vector<int>>& grid, int k) {
n = grid.size();
m = grid[0].size();
this->grid = move(grid);
this->k = k;
}
void rotate(int th) {
int m = this->m - 2 * th;
int n = this->n - 2 * th;
int all = (m + n) * 2 - 4;
int k = this->k % all;
vector<int> round;
round.reserve(all);
for (int j = 0; j < m - 1; j++) {
round.push_back(grid[th][th + j]);
}
for (int i = 0; i < n - 1; i++) {
round.push_back(grid[th + i][th + m - 1]);
}
for (int j = m - 1; j > 0; j--) {
round.push_back(grid[th + n - 1][th + j]);
}
for (int i = n - 1; i > 0; i--) {
round.push_back(grid[th + i][th]);
}
reverse(round.begin(), round.end());
reverse(round.begin(), round.begin() + all - k);
reverse(round.begin() + all - k, round.end());
int idx = 0;
for (int j = 0; j < m - 1; j++) {
grid[th][th + j] = round[idx++];
}
for (int i = 0; i < n - 1; i++) {
grid[th + i][th + m - 1] = round[idx++];
}
for (int j = m - 1; j > 0; j--) {
grid[th + n - 1][th + j] = round[idx++];
}
for (int i = n - 1; i > 0; i--) {
grid[th + i][th] = round[idx++];
}
}
public:
vector<vector<int>> rotateGrid(vector<vector<int>>& grid, int k) {
init(grid, k);
for (int th = 0; th < min(m, n) / 2; th++) {
rotate(th);
}
return move(this->grid);
}
};
C++ - GPT写的O(1)空间复杂度版本
相当于把人写的"临时放到数组中"的操作直接给写了个函数映射到原始矩阵中了。
cpp
/*
* @LastEditTime: 2026-05-09 22:42:01
*/
#ifdef _DEBUG
#include "_[1,2]toVector.h"
#endif
class Solution {
private:
int n, m, k;
vector<vector<int>> grid;
void init(vector<vector<int>>& grid, int k) {
n = grid.size();
m = grid[0].size();
this->grid = move(grid);
this->k = k;
}
pair<int, int> locate(int th, int idx) {
int m = this->m - 2 * th;
int n = this->n - 2 * th;
int top = th;
int bottom = th + n - 1;
int left = th;
int right = th + m - 1;
// 上
if (idx < m - 1) {
return {top, left + idx};
}
idx -= m - 1;
// 右
if (idx < n - 1) {
return {top + idx, right};
}
idx -= n - 1;
// 下
if (idx < m - 1) {
return {bottom, right - idx};
}
idx -= m - 1;
// 左
return {bottom - idx, left};
}
void reverse(int th, int l, int r) {
while (l < r) {
auto [x1, y1] = locate(th, l);
auto [x2, y2] = locate(th, r);
swap(grid[x1][y1], grid[x2][y2]);
l++;
r--;
}
}
void rotate(int th) {
int m = this->m - 2 * th;
int n = this->n - 2 * th;
int all = (m + n) * 2 - 4;
int k = this->k % all;
// 左轮转k次
reverse(th, 0, all - 1);
reverse(th, 0, all - k - 1);
reverse(th, all - k, all - 1);
}
public:
vector<vector<int>> rotateGrid(vector<vector<int>>& grid, int k) {
init(grid, k);
for (int th = 0; th < min(m, n) / 2; th++) {
rotate(th);
}
return move(this->grid);
}
};
同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源