1050. 螺旋矩阵

本题要求将给定的N个正整数按非递增的顺序,填入“螺旋矩阵”。所谓“螺旋矩阵”,是指从左上角第1个格子开始,按顺时针螺旋方向填充。要求矩阵的规模为m行n列,满足条件:m*n等于N;m>=n;且m-n取所有可能值中的最小值。

输入格式:

输入在第1行中给出一个正整数N,第2行给出N个待填充的正整数。所有数字不超过104,相邻数字以空格分隔。

输出格式:

输出螺旋矩阵。每行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. 读入N,声明gap用来存储m-n。
  3. i=1。n=i。m=N。gap=m-n。
  4. 如果i>sqrt(sum),那么就跳到第六步。否则进行下一步。
  5. 如果n%i==0 && gap > N/i - i,那么gap=N/i-i,m=N/i,n=i。i++。跳回第四步。
  6. 设置m行n列的二维数组,大小为N的数组。
  7. 读取N个正整数,并不递增地排序。
  8. 声明circle=0,声明i,j,count = 0。
  9. 如果circle不小于(n-1)/2,则跳到第二十八步。
  10. i=circle。
  11. 如果i大于n-1-circle,则跳到第十五步。
  12. 二维数组[circle][i]=数组[count++]。
  13. i++。回到第十二步。
  14. j=circle+1。
  15. 如果j大于m-1-cirlce,则跳到第十九步。
  16. 二维数组[j][n-1-circle]=数组[count++]。
  17. j++。回到第十六步。
  18. i=n-1-circle。
  19. 如果i小于零,则跳到第二十三步。
  20. 二维数组[m-1-circle][i]=数组[count++]。
  21. i--。回到第二十步。
  22. 如果n-1-circle<=circle,则跳到第二十七步。
  23. j=m-1-circle-1。
  24. 如果j不大于circle,则跳到第二十七步。
  25. 二维数组[j][circle]=数组[count++]。
  26. j--,回到第二十四步。
  27. circle++,回到第九步。
  28. 输出这个数组到屏幕上去。
  29. 算法结束。
时间复杂度:O(nlogn),空间复杂度:O(n)。注意:螺旋绕圈时不能覆盖之前的赋值过的数据。修改scanf_s函数就可以在PAT上运行。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int cmp(const void* v1, const void* v2);
int main(void) {
	int sum, m, n, i, j, count, circle, gap;
	int* array;
	int** helical;
	scanf_s("%d", &sum);
	if (sum) {
		array = (int*)calloc(sum, sizeof(int));
		m = sum;
		n = 1;
		gap = m - n;
		i = 2;
		j = (int)sqrt(sum);
		while (i <= j) {
			if (sum%i == 0 && sum / i - i < gap) {
				m = sum / i;
				n = i;
				gap = sum / i - i;
			}
			i++;
		}
		
		helical = (int**)calloc(m, sizeof(int*));
		for (i = 0; i < m; i++) {
			helical[i] = (int*)calloc(n, sizeof(int));
		}
		for (i = 0; i < sum; i++) {
			scanf_s("%d", array + i);
		}
		qsort(array, sum, sizeof(int), cmp);
		circle = 0;
		count = 0;
		while (circle <= (n - 1) / 2) {
			for (i = circle; i < n - circle; i++) {
				helical[circle][i] = array[count++];
			}
			for (i = circle + 1; i < m - circle; i++) {
				helical[i][n - 1 - circle] = array[count++];
			}
			for (i = n - 2 - circle; i >= circle; i--) {
				helical[m - 1 - circle][i] = array[count++];
			}
			if (n - 1 - circle > circle) {
				for (i = m - 2 - circle; i >= circle + 1; i--) {
					helical[i][circle] = array[count++];
				}
			}
			circle++;
		}
		for (i = 0; i < m; i++) {
			printf("%d", helical[i][0]);
			for (j = 1; j < n; j++) {
				printf(" %d", helical[i][j]);
			}
			if (i != m - 1) {
				putchar('\n');
			}
		}
		free(array);
		for (i = 0; i < m; i++) {
			free(helical[i]);
		}
		free(helical);
	}
	else {
		putchar('\0');
	}
	return 0;
}
int cmp(const void* v1, const void* v2) {
	return *((int*)v2) - *((int*)v1);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值