每天一道算法题——螺旋数组

给定一个正整数 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);
}

猜你喜欢

转载自blog.csdn.net/m0_58768224/article/details/129760297