59. 螺旋矩阵 II - 力扣(LeetCode)
题目标签:数组、
题目简述:将一个数组,螺旋地写进方阵中
相似题目:
- 解题思路:
- 操作坐标增量
- 使用方向向量
dx
,dy
对x
与y
进行操作 x = x +dx; y = y + dy;
- 注意事项:
- 第一次在做题目时候没有使用使用nx 与ny 做为中间变量导致数组访问越界。下面浅析一下原因:
- 如果直接修改 x 和 y,那么在下一个判断条件或操作中使用 x 和 y 时,就会使用已经被修改过的值,这可能导致逻辑错误或意外的行为。通过先计算 nx 和 ny,我们可以在确认它们是有效位置之后再更新 x 和 y。
- 使用方向向量
- 坐标循环
- 使用四个for循环控制四个方向上坐标的变化
- 操作坐标增量
// 简单例子
x += dx[direction];
y += dy[direction];
if (/* 检查 (x, y) 是否有效 */) {
// ... 填充矩阵等操作 ...
} else {
// 如果 (x, y) 无效,我们就需要往后退一步,不然就是在边界外向沿着更新的方向前进
x -= dx[direction];
y -= dy[direction];
// 然后改变方向并重新计算新的位置
}
- 代码:
// 个人解法 同acwing
## 一. 操作坐标的增量
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0));
vector<vector<bool>> status(n, vector<bool>(n, false));
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int x = 0, y = 0;
int c = 0; //初始方向
// 循环量的更新不会,导致超出边界
for(int i = 1; i <= n*n; i++) {
res[x][y] = i;
status[x][y] = true;
// 定义下个点的位置,并且在最后放回
int nx = x + dx[c % 4];
int ny = y + dy[c % 4];
if(nx < 0 || nx >= n || ny < 0 || ny >= n || status[nx][ny]) {
c ++;
// 如果超出边界,就要重新定义 下个点的位置
nx = x + dx[c % 4];
ny = y + dy[c % 4];
}
x = nx;
y = ny;
}
return res;
}
};
// 二. 坐标循环
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
int count = 1; // 用来给矩阵中每一个空格赋值
int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
int i,j;
while (loop --) {
i = startx;
j = starty;
// 下面开始的四个for就是模拟转了一圈
// 模拟填充上行从左到右(左闭右开)
for (j = starty; j < n - offset; j++) {
res[startx][j] = count++;
}
// 模拟填充右列从上到下(左闭右开)
for (i = startx; i < n - offset; i++) {
res[i][j] = count++;
}
// 模拟填充下行从右到左(左闭右开)
for (; j > starty; j--) {
res[i][j] = count++;
}
// 模拟填充左列从下到上(左闭右开)
for (; i > startx; i--) {
res[i][j] = count++;
}
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
startx++;
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset += 1;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if (n % 2) {
res[mid][mid] = count;
}
return res;
}
};