原地旋转矩阵需分层处理,每层用四元轮换更新上、右、下、左四边元素,第k层遍历n−2k−1次,奇数阶最内层单元素不操作,避免数据覆盖。

原地旋转矩阵必须分层处理
直接遍历交换会导致数据被覆盖,必须把 n x n 矩阵看作若干嵌套的正方形“环”,从外向内逐层旋转。每层只处理上边(不含右端点)、右边(不含下端点)、下边(不含左端点)、左边(不含上端点)这四段,用一个临时变量暂存上边元素即可完成一圈轮换。
常见错误是循环边界写错:第 k 层(从 0 开始)的边长为 n - 2*k,该层索引范围是 [k, n-1-k],但轮换时只需遍历 n - 2*k - 1 次——因为四个角在一次轮换中已同步更新,多跑一次就重复了。
- 对
4x4矩阵,第 0 层需轮换 3 次,不是 4 次 - 当
n为奇数时,最内层是单个元素(如5x5的中心位置[2][2]),无需操作 - 不要试图用
swap()两两交换替代四元轮换,会破坏顺序
std::vector<:vector>></:vector> 原地旋转的 C++ 实现
以下代码严格按层 + 四元轮换实现,不依赖额外空间(除几个 int 变量):
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int k = 0; k < n / 2; ++k) {
int len = n - 2 * k - 1;
for (int i = 0; i < len; ++i) {
int tmp = matrix[k][k + i];
matrix[k][k + i] = matrix[n-1-k-i][k];
matrix[n-1-k-i][k] = matrix[n-1-k][n-1-k-i];
matrix[n-1-k][n-1-k-i] = matrix[k+i][n-1-k];
matrix[k+i][n-1-k] = tmp;
}
}
}
注意四次赋值的坐标顺序:上 → 左 → 下 → 右 → 上(由 tmp 补回)。若顺序颠倒(比如先改左再读左),就会读到已被覆盖的值。
立即学习“C++免费学习笔记(深入)”;
-
matrix[k][k+i]是上边第i个元素(行固定为k,列递增) -
matrix[n-1-k-i][k]是左边第i个元素(列固定为k,行递减) - 所有下标都基于当前层左上角
(k,k)和边长推导,不查表、不硬编码
坐标变换公式容易记混?直接用几何映射理解
顺时针旋转 90° 的本质是:原坐标 (i, j) 映射到新位置 (j, n-1-i)。但这仅适用于「生成新矩阵」场景;原地旋转不能直接套用,因为写入新位置时旧值已丢失。
真正能用的坐标关系,是同一层内四个对称位置的联动规律。设当前层左上角为 (k, k),则对偏移量 i(0 ≤ i ):
<ul>
<li>上边点:<code>(k, k+i)
(k+i, n-1-k)
(n-1-k, n-1-k-i)
(n-1-k-i, k)
这组坐标恰好构成一个顺时针环——轮换顺序就是按这个环走一遍。死记 (j, n-1-i) 容易在原地操作时绕晕,不如盯住一层画个草图,标出四个点,再手推一遍赋值链。
测试时别漏掉 1x1 和 2x2 这类边界情况
rotate() 函数里 n / 2 作为外层循环上限,对 n=1 直接跳过循环,正确;对 n=2 循环一次(k=0),len = 1,执行一次四元轮换,也正确。但如果你误写成 k 或 <code>len ,<code>2x2 就会越界或少转。
建议用这几个输入快速验证:
-
[[1]]→ 仍为[[1]] -
[[1,2],[3,4]]→ 应变为[[3,1],[4,2]] -
[[1,2,3],[4,5,6],[7,8,9]]→ 中心5不动,其余顺时针流转
最容易被忽略的是:原地算法对内存布局敏感,务必确保传入的是引用 vector<vector>>&</vector>,而非值传递;否则函数内修改根本不会反映到调用方。


















