蛇形数组


题目要求

给定一个整形数N,要求形成一个N * N的矩阵。矩阵中的每一项存放的数从1到N * N,以蛇形迂回的顺序存放。最后按行按列依次输出数组中的元素。

例如 3 * 3 的数组存放情况如下:
1 2 3
8 9 4
7 6 5

例如 5 * 5数组存放情况如下:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

样例输入:3

输出:1 2 3 8 9 4 7 6 5(每一位数之间有一空格)

样例输入:5

输出:1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9(每一位数之间有一空格)

解题思路

虽然说题目是要求生成一个二位数组,其实也可以用一个一维数组来存储,通过计算,把二位数组的下标转换成一维数组的下标。比如一个4 * 4的数组,第2行第3列的行数本来用二维数组存储的位置是 int[1][2],换算成一维数组则是 int[2 * 4 + 3 - 1],即 int[10]的位置。

具体在存放数的时候,是模拟蛇形迂回的路线存放的,从1~N * N的顺序填满数组。可以把存数的动作分解成一轮轮,每一轮把一个数组最外圈的位置填满,然后递归填满向里面的一圈。比如对于一个 6 * 6 的数组A,第一轮把最外圈上→右→下→左的边共20个位置依次用1~20顺序填满。这样完成第一轮后,剩下未填满的是一个4 * 4的数组,记作数组B。接下来用21~32共12个数依次把数组B上右下左的边一次填满。这样每次递归完成存数。注意设立递归基,以及考虑原始数组边长度奇偶性对最后一次递归的影响。

代码实现

#include<iostream>
using namespace std;

void createSnakeArr(int startNum, int currx, int curry, int a[], int currSize, int totalSize) {
    int n = startNum;   // startNum 为新开始一轮存放的第一个数
    int x = currx;      // currx 为当前一轮存放第一个数的行数
    int y = curry;      // curry 为当前一轮存放第一个数的列数
    if (currSize < 1) return;   // 递归基, currSize为当前这一轮数组的大小
    if (currSize == 1) {        // 处理 N * N 数组(N为奇数时最后一轮时最后一个数的存放)  
        a[x * totalSize + y] = n;
        cout << n << ": " << x << " " << y << endl;
        return;
    }
    while (n < startNum + 4 * currSize - 4) {
        if (x == currx && y < curry + currSize - 1) {
            // 填满上方一行 
            a[x * totalSize + y] = n;
            y++;
            n++;
        }
        if (y == curry + currSize - 1 && x < currx + currSize - 1) {
            // 填满右边一列
            a[x * totalSize + y] = n;
            x++;
            n++;
        }
        if (x == currx + currSize - 1 && y > curry) {
            // 填满下方一行
            a[x * totalSize + y] = n;
            y--;
            n++;
        }
        if (y == curry && x > currx) {
            // 填满左边一列
            a[x * totalSize + y] = n;
            x--;
            n++;
        }
    }
    // 递归生成小一圈的数组
    createSnakeArr(a[(currx + 1) * totalSize + curry] + 1, currx + 1, curry + 1, a, currSize - 2, totalSize);
} 

    void printArray(int *a, int length) {
    cout << a[0];
    for (int i = 1; i < length; i++) {
        cout << " " << a[i];
    }
    cout << endl;   
}

int main() {
    int N;
    cin >> N;
    int n = N * N;
    int *snakeArr = new int[n];
    createSnakeArr(1, 0, 0, snakeArr, N, N);
    printArray(snakeArr, n);
    delete []snakeArr;
    return 0;
}