给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
代码随想录版本:
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;
}
};
scwing版本:
#include <bits/stdc++.h>
using namespace std;
const int maxn=110;
int a[maxn][maxn]; //定义空的二维数组数组
int dx[]={-1,0,1,0},dy[]={0,1,0,-1}; //初始化方向所对应的偏移量的数组(偏移量就是在该方向移动时索引应当进行的变化是什么样的)
int main()
{
int n,m;
cin>>n>>m;
int dr=1,x=0,y=0; //初始化开始方向为右,初始化开始的位置
for(int i=1;i<=n*m;i++){
a[x][y]=i; //存入答案
int h=x+dx[dr],l=y+dy[dr]; //定义临时变量存放(x,y)的下一个位置的坐标
if(h<0||l<0||h>=n||l>=m||a[h][l]){ //判断
dr=(dr+1)%4; //方向改变,实际上方向对应的就是两个偏移量数组的索引
h=x+dx[dr],l=y+dy[dr];
}
x=h,y=l; //更新(x,y)
}
for(int i=0;i<n;i++){ //循环打印输出
for(int j=0;j<m;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
也可以叫蛇形数组
自己用js实现的版本:
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
/* 输入在一行,用空格分隔,拼接为数组 */
rl.on("line", function (line) {
let array = line.split(" ").map(Number);
let n = array[0];
let m = array[1];
//console.log(typeof n);
//console.log(typeof m);
let xarr = [0, 1, 0, -1];
let yarr = [1, 0, -1, 0];
let f = 0;
let x = 0;
let y = 0;
let p = 0; //临时变量,用来存储下一步要到的坐标
let q = 0; //临时变量,用来存储下一步要到的坐标
var resArray = new Array(n);
for (var i = 0; i < resArray.length; i++) {
resArray[i] = new Array(m);
}
// let resArray = new Array[n][m]();
for (let i = 1; i <= n * m; i++) {
// console.log(x, y);
resArray[x][y] = i;
p = x + xarr[f]; //注意点:要先用临时变量存储下一步的位置进行判断,然后改变方向,否则都已经越界了再改变方向就没有意义了
q = y + yarr[f];
if (p < 0 || p >= n || q < 0 || q >= m || resArray[p][q]) { //注意边界值,要>=n,因为n-1是索引的最后位置,而不是n
f = (f + 1) % 4;
x += xarr[f]; //改变方向之后走一步
y += yarr[f];
} else {
x += xarr[f]; //直接走一步
y += yarr[f];
}
}
// console.log(resArray);
// for (let i = 0; i < resArray.length; i++) {
// for (let j = 0; j < resArray[i].length; j++) {
// console.log(resArray[i][j]);
// }
// }
resArray.map((value) => {
console.log(value.join(" "));
});
});
注意:js中创建二维数组需要使用for循环,因为js本身是没有二维数组这种类型的!
//创建n行m列的数组
var resArray = new Array(n);
for (var i = 0; i < resArray.length; i++) {
resArray[i] = new Array(m);
}