C语言算法题:螺旋矩阵

文章目录

  • 一、题目
  • 二、思路
    • 1、暴力解法
    • 2、进阶递归
  • 三、代码
    • 1、暴力解法
    • 2、进阶递归

一、题目

一个 nn 行 nn 列的螺旋矩阵可由如下方法生成:

从矩阵的左上角(第 11 行第 11
列)出发,初始时向右移动;如果前方是未曾经过的格子,则继续前进,否则右转;重复上述操作直至经过矩阵中所有格子。根据经过顺序,在格子中依次填入
11, 22 , 33, … , nn ,便构成了一个螺旋矩阵。

下图是一个 n = 4 时的螺旋矩阵。
C语言算法题:螺旋矩阵_第1张图片

输入格式:

输入共一行,包含三个整数 n,i,jn,i,j ,每两个整数之间用一个空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。

输出格式:

输出一个整数,表示相应矩阵中第 ii 行第 jj 列的数。

数据范围 对于 50%50% 的数据, 1 \le n \le 1001≤n≤100 ;

对于 100%100% 的数据, 1 \le n \le 30,0001≤n≤30,000 , 1 \le i \le n,1 \le j
\le n1≤i≤n,1≤j≤n

Sample Input:

4 2 3

Sample Output:

14

二、思路

当n=4时,螺旋矩阵如下:
C语言算法题:螺旋矩阵_第2张图片
当n=5时,螺旋矩阵如下:
C语言算法题:螺旋矩阵_第3张图片

1、暴力解法

我们先找到螺旋的四个角的坐标:
(0,0)->(0,n - 1)->(n - 1,n - 1)->(n - 1,0)
这样一次是一个循环。

然后我们可以确定循环的次数,不超过 n / 2 次(n为偶数的情况),但是当 n 为奇数的时候,矩阵的中心的值为 n * n,我们可以单独讨论。

通过观察螺旋矩阵,我们通过其原理可以发现,其坐标有如下规律:

当矩阵的方向为:“向右” ,此时坐标的纵坐标不变,横坐标++;
改变范围:0 ~ n - 1
当矩阵的方向为:“向下” ,此时坐标的纵坐标++,横坐标不变;
改变范围:0 ~ n - 1
当矩阵的方向为:“向左” ,此时坐标的纵坐标不变,横坐标–;
改变范围:n - 1 ~
当矩阵的方向为:“向上” ,此时坐标的纵坐标–,横坐标不变;
改变范围:

通过以上坐标的基础规律,我们就可以用四个for循环来完成对矩阵的值的输入.

易错提示:
但是由于使用到了数组,所以在实际输出的时候,我们需要将坐标–;才能达到正确输出的目的。

2、进阶递归

掌握了基础解法以后,继续观察矩阵,我们还能发现以下规律:

n = 4时为例
C语言算法题:螺旋矩阵_第4张图片
我们可以发现,里层实际上也是一个螺旋矩阵,只不过是初始值变成了12,而阶数(n)减少了2,所以我们可以每次只表示一圈,然后进行递归,同样可以表示出螺旋矩阵。

对于阶数(n)的奇偶,结束的标准也不同,所以我们需要进行分类讨论:
①奇数的结束是矩阵的中心(n * n);
②偶数的结束是最里层的矩阵(n = 2,只是初始值改变了)

经过上一次坐标出错后,我们索性直接从1开始遍历(这样坐标就不用–了)。

三、代码

1、暴力解法

#include
int main()
{
	int n,i,j;
	scanf("%d %d %d",&n,&i,&j);
	int x[300][300] = {1};// 将数组初始化为1,考虑了n = 1时的情况 
	int a,b;
	int num = 1;
	for(a = 0;a <= n/2;a++)
	{
		// 上边框 
		for(b = a;b <= n - a -1;b++)
			x[a][b] = num++;
		// 右边框
		for(b = a + 1;b <= n - a - 1;b++)
			x[b][n - a - 1] = num++;
		// 下边框
		for(b = n - a - 2;b >= a;b--)
			x[n - a - 1][b] = num++;
		// 左边框
		for(b = n - a - 2;b > a;b--)
			x[b][a] = num++;
		// n为奇数的情况
		if(n % 2 == 1)
			x[n/2][n/2] = n * n; 
	}
	printf("%d",x[i - 1][j - 1]);
	return 0;
}

2、进阶递归

#include
int a[300][300] = {0};
void func(int num,int max,int len,int t,int n)
{
	if(len == 1)// n为奇数时,结束的标志 
	{
		a[t][t] = num;
	}
	else if(len == 2)// n为偶数时,结束的标志 
	{
		a[t][t] = num++;
		a[t][t+1] = num++;
		a[t + 1][t + 1] = num;
		a[t + 1][t] = max;
		return;
	}
	int flag = n + 1 - t;
	int Num = num;
	int i,j = 0;
	// 上边框 
	for(j = t;j <= flag;j++)
		a[t][j] = Num++;
	// 右边框 
	for(i = t + 1;i <= flag;i++)
		a[i][flag] = Num++;
	// 下边框 
	for(j = flag - 1;j >= t;j--)
		a[flag][j] = Num++;
	// 左边框 
	for(i = flag - 1;i >= t + 1;i--)
		a[i][t] = Num++;
	func(Num,n * n,len - 2,t + 1,n);
}
int main()
{
	int n,i,j;
	scanf("%d %d %d",&n,&i,&j);
	func(1,n * n,n,1,n);
	printf("%d",a[i][j]);
	return 0;
}

你可能感兴趣的:(C语言算法题,矩阵,c语言,算法)