题目
本题要求将给定的N个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第1个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为m行n列,满足条件:m*n等于N;m>=n;且m-n取所有可能值中的最小值。
输入格式:
输入在第1行中给出一个正整数N,第2行给出N个待填充的正整数。所有数字不超过10^4^,相邻数字以空格分隔。
输出格式:
输出螺旋矩阵。每行n个数字,共m行。相邻数字以1个空格分隔,行末不得有多余空格。
输入样例:
12
37 76 20 98 76 42 53 95 60 81 58 93
输出样例:
98 95 93
42 37 81
53 20 76
58 60 76
实现思路:先计算出矩阵的行与列,然后按照定义,一圈一圈循环赋值,最后输出数组
1.输入;
2.从平方根向前寻找整除项,第一个即可,定义矩阵数组;(注:如果存在整数平方根,则即为结果,m=n,如果不存在,则离平方根最近的整除项的差值最小,另外不能向后寻找,因为sqrt函数返回double类型,转换为int会向下取整,有可能刚好可以整除,如12的平方根大概是3.46,取int为3,而刚好可以整除,最大最小值会相反)
3.圈数即为n/2,分成4部分循环赋值,最后如果n是奇数,处理最后剩下的中间一列;
4.输出。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int cmp(const void *a, const void *b)
{
return *((int *)b)-*((int *)a);
}
int main()
{
int n=0;
scanf("%d",&n);
int iData[n];
for(int i=0;i<n;i++)
{
scanf("%d",&iData[i]);
}
qsort(iData,n,sizeof(int),cmp);
int iM=0,iN=0;
// int iMin=n;
// for(int i=1;i<sqrt(n)+1;i++)
// {
// if(n%i==0)
// {
// if(iMin>=(n/i-i))
// {
// iMin=n/i-i;
// iM=n/i;
// iN=i;
// }
// }
// }
for(int i=(int)sqrt(n);i>0;i--)//从平方根反向寻找,效率更高
{
if(n%i==0)
{
iM=n/i;
iN=i;
break;
}
}
int iOut[iM][iN];
int p=0,q=0;//p为圈数,q为原数组下标
while(p<iN/2)
{
for(int i=p;i<iN-p-1;i++)//圈上
{
iOut[p][i]=iData[q++];
}
for(int i=p;i<iM-p-1;i++)//圈右
{
iOut[i][iN-p-1]=iData[q++];
}
for(int i=iN-p-1;i>p;i--)//圈下
{
iOut[iM-p-1][i]=iData[q++];
}
for(int i=iM-p-1;i>p;i--)//圈左
{
iOut[i][p]=iData[q++];
}
p++;
}
if(iN%2==1)//处理中间一列
{
for(int i=p;i<iM-p;i++)
{
iOut[i][iN/2]=iData[q++];
}
}
//循环输出
for(int i=0;i<iM;i++)
{
for(int j=0;j<iN;j++)
{
if(i==0&&j==0)
{
printf("%d",iOut[i][j]);
}
else if(j==0)
{
printf("\n%d",iOut[i][j]);
}
else
{
printf(" %d",iOut[i][j]);
}
}
}
return 0;
}
错误分析:
1.奇数的中间一列无法界定上下左右,感觉逻辑基础不同,暂时合并不到整体结构中去;
2.注意螺旋赋值的时候的变量意义,都与圈数有关,不能出现无关圈数的元素;
3.这样直接分段赋值的操作没有数组越界的风险,不需要更大的二维数组。