递归法求螺旋矩阵
问题描述:
给定一n维矩阵,有如下规律:
矩阵维数为1时,矩阵为:
1 |
---|
矩阵维数为2时,矩阵为:
1 | 2 |
---|---|
4 | 3 |
矩阵维数为3时,矩阵为:
1 | 2 | 3 |
---|---|---|
8 | 9 | 4 |
7 | 6 | 5 |
矩阵维数为4时,矩阵为:
1 | 2 | 3 | 4 |
---|---|---|---|
12 | 13 | 14 | 5 |
11 | 16 | 15 | 6 |
10 | 9 | 8 | 7 |
矩阵维数为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 |
依次类推。。。
问题解决思路:
此题乍一看比较复杂但是我们可以观察数的规律,每一个圈中数都是从左上角顺时针依次增1,因此我们可以将此题转换成填圈从外圈填到内圈直到填满为止,那么我们接下来就以最外圈举例:
我们先从左到右将行填满,这需要我们知道左下角的元素值,我们其实可以通过数学证明出左下角的值等于左上角的值加上3*(n-1),n为外圈的行数,这样我们就可以填充了,上面一行依次加1,下面一行依次减1,然后填列,我们可以从下到上去填充,左边的列依次加1,右边的列依次减1。
这圈填完后就进入次外圈即可,依次类推。
c语言实现源代码:
#include<iostream>
using namespace std;
/**
* function:求解螺旋矩阵
* first:首元素(即矩阵左上角元素)的值
* i:首元素(即矩阵左上角元素)的下标
* n:子矩阵长度
* m:螺旋矩阵
*/
void spiralmatrix(int first,int i, int n, int** m) {
if (n == 1) {//n为1时,该子矩阵就一个元素,即first
m[i][i] = first;
}
else if (n == 2) {//n为2时,该子矩阵首元素为first的螺旋矩阵,直接赋值即可
m[i][i] = first;
m[i][i + 1] = first + 1;
m[i + 1][i + 1] = first + 2;
m[i + 1][i] = first + 3;
}
/**
* 当n>2时,情况比较复杂,左上角的值等于first,左下角的值等于first+3*(n-1),
* 然后按列补全第i行和第i+n-1行,其中第i行和第i+n-1行所有元素其中第i行是依次增1,第i+n-1行依次减1
* 然后再按行补齐第i列和第i+n-1列,其中第i行和第i+n-1行所有元素其中第i列是依次增1,第i+n-1列依次减1(按照从下向上填充)
* 最后外圈补齐后,进入内圈(利用递归法即可),这步的关键是求出左上角的元素值、左上角元素行下标、子矩阵长度
*/
else {
m[i][i] = first;
m[i + n - 1][i] = 3 * (n - 1) + first;
for (int j = i + 1; j <= i + n - 1; j++){
m[i + n - 1][j] = m[i + n - 1][j - 1] - 1;
m[i][j] = m[i][j - 1] + 1;
}
for (int j = i + n - 2; j > i; j--) {
m[j][i] = m[j + 1][i] + 1;
m[j][i + n - 1] = m[j + 1][i + n - 1] - 1;
}
spiralmatrix(first + 4 * (n - 1), i + 1, n - 2, m);
}
}
int main() {
int** m;
int n;
cout << "请输入矩阵的维数:";
cin >> n;
m = new int* [n];
for (int i = 0; i < n; i++) {
m[i] = new int[n];
}
spiralmatrix(1, 0, n, m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << m[i][j] << "\t";
}
cout << "\n";
}
for (int i = 0; i < n; i++) {
delete[] m[i];
}
delete[] m;
}
运行结果如下:
算法复杂度分析:
不难看出此算法为O(n^2)
源代码已上传GitHub,请点击获取