一. 这题看到最初的想法感觉和某道题比较像,不过不记得了............就是从[0,0]点出发,遇到边界就换个方向,然后边界还要更新.
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//初始化一个二维结果矩阵.
vector<vector<int>> res(n, vector<int>(n, 0));
//初始化一个方向矩阵,顺序是有讲究的,右->下->左->上,循环往复.
vector<char> direct = { 'R', 'D', 'L', 'U' };
int num = 0, count=1;//count计算生成了多少个数.
int x = 0, y = -1;//初始化点的坐标.
//边界初始化,注意upboard为1,因为第一行走的时候占据了.
int leftboard = 0, rightboard = n - 1, upboard = 1, downboard = n - 1;
while(count<=n*n) {
//方向,注意模4代表循环往复.
char d = direct[num % 4];
if (d == 'R') {
//先走完右边.
while (y != rightboard) {
y++;
res[x][y] = count;
count++;
}
//更新边界.
rightboard--;
}
if (d == 'D') {
while (x != downboard) {
x++;
res[x][y] = count;
count++;
}
downboard--;
}
if (d == 'L') {
while (y != leftboard) {
y--;
res[x][y] = count;
count++;
}
leftboard++;
}
if (d == 'U') {
while (x != upboard) {
x--;
res[x][y] = count;
count++;
}
upboard++;
}
num++;
}
return res;
}
};
二. 参考一下大神们的题解.
思路:
1. 生成一个 n×n 空矩阵 mat,随后模拟整个向内环绕的填入过程:
2. 定义当前左右上下边界 l,r,t,b,初始值 num = 1,迭代终止值 tar = n * n;当 num <= tar 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后:
3. 执行 num += 1:得到下一个需要填入的数字;更新边界:例如从左到右填完后,上边界 t += 1,相当于上边界向内缩 1。使用num <= tar而不是l < r || t < b作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。最终返回 mat 即可。
4. 方法和我的几乎一样,只不过边界向内收缩的形式不太一样.
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
// 创建二维矩阵
vector<vector<int>> matrix(n, vector<int>(n, 0));
// 上下左右
int u = 0;
int d = n - 1;
int l = 0;
int r = n - 1;
int num = 1;
while (num <= n*n) {
// 上
for (int i = l; i <= r; i++) matrix[u][i] = num++;
u++;
// 右
for (int i = u; i <= d; i++) matrix[i][r] = num++;
r--;
// 下
for (int i = r; i >= l; i--) matrix[d][i] = num++;
d--;
// 左
for (int i = d; i >= u; i--) matrix[i][l] = num++;
l++;
}
return matrix;
}
};
5. 不得不说,大神的代码还是简洁.首先循环往复直接用的while, 然后直接通过边界计算相应的位置.佩服.
6. 复杂度分析
时间复杂度:O(n^2)我们填充时遍历一次矩阵,矩阵元素个数为 n^2.
空间复杂度:O(n^2)需要一个矩阵 resultMatrix 存储结果.