蛇形数组
题目要求
给定一个整形数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;
}