【PAT】1105 Spiral Matrix(柳婼的思想详细解读)

31 篇文章 2 订阅
14 篇文章 0 订阅

【PAT】1105 Spiral Matrix

用的就是是柳大姐的思想:柳姐传送门
先计算行数m和列数n的值,n从根号N的整数部分开始,往前推一直到1,找到第一个满足N % n== 0的,m的值等于N/n~将N个给定的值输入数组a,并将a数组中的值按非递增排序,接着建立m行n列的数组b,填充时按层数填充,一个包裹矩阵的口字型为一层,计算螺旋矩阵的层数level,如果m的值为偶数,层数为m/2,如果m为奇数,层数为m/2+1,所以level = m / 2 + m % 2;因为是从左上角第1个格子开始,按顺时针螺旋方向填充,所以外层for循环控制层数i从0到level,内层for循环按左上到右上、右上到右下、右下到左下、左下到左上的顺序一层层填充,注意内层for循环中还要控制t <= N – 1,因为如果螺旋矩阵中所有的元素已经都填充完毕,就不能再重复填充~填充完毕后,输出整个矩阵~
在这里插入图片描述
下面以一个5*4的矩阵为例:(m=5,n=4)
在这里插入图片描述
可以看到每一层都需要分为四个步骤进行填充数字。若将元素的下标看成是一个x,y的坐标,我们很容易就可以总结出①②③④遍历过程中x,y的取值范围。其中i表示正在填充第i层,从0开始。

① x:i              y:i ~ n-i-1
② x:i+1 ~ m-i-2    y:n-i-1
③ x:m-1-i          y:n-i-1 ~ i
④ x:m-i-2 ~ i+1    y: i

在每一轮循环遍历的过程中,我们还需要进行 cnt <= N - 1 的判断(否则会有测试点通不过,例如:只有19个元素,13个元素的时候,大家可以试一试)。其中cnt表示已经填充元素的个数,而N表示元素总个数。

AC代码:

#include<bits/stdc++.h>
using namespace std;
vector<int> v;
int cmp(int a, int b) {
	return a > b;
}
int main() {
	int N,m,n; scanf("%d", &N);
	for (int i = 0; i < N; i++) {
		int temp; scanf("%d", &temp);
		v.push_back(temp);
	}
	sort(v.begin(), v.end(), cmp);
	n = (int)sqrt(N);
	while (N%n) n++;//N%n==0时退出循环
	m = N / n;
	if (m < n) swap(n, m);//保持m>=n;
	vector<vector<int> > ans(m, vector<int>(n));
	int level = n / 2 + n % 2;//计算一共有几层。
	int cnt = 0;//记录当前数组的下标
	for (int i = 0; i < level; i++) {//此时开始遍历每一层
		for (int j = i; j < n - i && cnt <= N - 1; j++)//①
			ans[i][j] = v[cnt++];
		for (int j = i + 1; j < m - i - 1 && cnt <= N - 1; j++) //②
			ans[j][n - 1 - i] = v[cnt++];
		for (int j = n - i - 1; j >= i && cnt <= N - 1; j--)//③
			ans[m - i - 1][j] = v[cnt++];
		for (int j = m - i - 2; j >= i + 1 && cnt <= N - 1; j--)//④
			ans[j][i] = v[cnt++];
	}
	for (int i = 0; i < m; i++) {
		cout << ans[i][0];
		for (int j = 1; j < n; j++) {
			cout<<" "<< ans[i][j];
		}
		cout << endl;
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值