經典面試/筆試題:給定 N×N 矩陣,原地或輔助空間實現順時針/逆時針 90°、180° 旋轉及轉置。本文提供清晰的索引映射規律、完整 C++ 代碼、時空複雜度分析及原地旋轉進階方案。
| 操作 | 目標位置 [i][j] ← 源位置 | 幾何含義 |
|---|---|---|
| 順時針 90° | mat[i][j] = src[N-1-j][i] | 列變行,行索引反轉 |
| 逆時針 90° | mat[i][j] = src[j][N-1-i] | 行變列,列索引反轉 |
| 180° | mat[i][j] = src[N-1-i][N-1-j] | 行列雙反轉 |
| 主對角線轉置 | mat[i][j] = src[j][i] | 行列互換 |
| 副對角線轉置 | mat[i][j] = src[N-1-j][N-1-i] | 行列互換+雙反轉 |
#include <iostream>
#include <vector>
using namespace std;
using Matrix = vector<vector<int>>;
Matrix rotate90Clockwise(const Matrix& src) {
int n = src.size();
Matrix dst(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
dst[i][j] = src[n - 1 - j][i];
return dst;
}
Matrix rotate90CounterClockwise(const Matrix& src) {
int n = src.size();
Matrix dst(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
dst[i][j] = src[j][n - 1 - i];
return dst;
}
Matrix rotate180(const Matrix& src) {
int n = src.size();
Matrix dst(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
dst[i][j] = src[n - 1 - i][n - 1 - j];
return dst;
}
Matrix transpose(const Matrix& src) {
int n = src.size();
Matrix dst(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
dst[i][j] = src[j][i];
return dst;
}
void printMatrix(const Matrix& m) {
for (const auto& row : m) {
for (int v : row) cout << v << '\t';
cout << '\n';
}
}
int main() {
Matrix mat = {{1,2,3}, {4,5,6}, {7,8,9}};
cout << "Original:\n"; printMatrix(mat);
cout << "\nClockwise 90:\n"; printMatrix(rotate90Clockwise(mat));
cout << "\nCounterClockwise 90:\n"; printMatrix(rotate90CounterClockwise(mat));
cout << "\n180:\n"; printMatrix(rotate180(mat));
cout << "\nTranspose:\n"; printMatrix(transpose(mat));
return 0;
}
Original: 1 2 3 4 5 6 7 8 9 Clockwise 90: 7 4 1 8 5 2 9 6 3 CounterClockwise 90: 3 6 9 2 5 8 1 4 7 180: 9 8 7 6 5 4 3 2 1 Transpose: 1 4 7 2 5 8 3 6 9
分層旋轉,每層四邊元素四向循環交換。
void rotate90InPlace(Matrix& mat) {
int n = mat.size();
for (int layer = 0; layer < n / 2; ++layer) {
int first = layer;
int last = n - 1 - layer;
for (int i = first; i < last; ++i) {
int offset = i - first;
int top = mat[first][i]; // 保存上邊
// 左 → 上
mat[first][i] = mat[last - offset][first];
// 下 → 左
mat[last - offset][first] = mat[last][last - offset];
// 右 → 下
mat[last][last - offset] = mat[i][last];
// 上(保存) → 右
mat[i][last] = top;
}
}
}
| 方法 | 時間 | 空間 | 適用場景 |
|---|---|---|---|
| 輔助矩陣 | O(N²) | O(N²) | 面試速寫、只讀源矩陣、非方陣擴展 |
| 原地分層 | O(N²) | O(1) | 內存受限、大矩陣、嵌入式 |
dst[j][M-1-i] = src[i][j]n/2,奇數階中心元素不動。矩陣旋轉是考察索引操作、邊界控制、空間優化的綜合題。掌握「轉置 + 翻轉」等價變換(順時針 90° = 轉置 + 左右翻轉),能靈活應對各種變體。