1105 Spiral Matrix 给定数组向螺旋矩阵中填入数据
Posted CSU迦叶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1105 Spiral Matrix 给定数组向螺旋矩阵中填入数据相关的知识,希望对你有一定的参考价值。
两个测试用例超时,可直接跳转到
目录
要做的事情是,将数组按照非升序/降序,顺时针从外围到内部一圈一圈地把数据填到矩阵中,并打印出来。也就是将数组排好序后,将矩阵的坐标和数组的下标对应起来。
所以用一个这样的数组存放矩阵相应位置上元素的数组下标。
int mp[200][200] = {0};
起先,我这样填充每一圈(注意交点的分配)
当然,从外到内,这个圈一定是在减小的, 减小多少,我用z来控制,程序如下,4个for循环分别代表4条直线上的元素
int idx = n-1,i,j,z=1;
int sw = false;//stop while循环
for(z=1;;z++){
i = z;
if(sw)break;
for(j=z;j<=col-z;j++){
mp[i][j] = idx--;
// printf("mp[%d][%d]=%d\\n",i,j,idx+1);
if(idx<0){
sw = 1;
break;
}
}
j = col+1-z;
if(sw)break;
for(i=z;i<=row-z;i++){
mp[i][j] = idx--;
// printf("mp[%d][%d]=%d\\n",i,j,idx+1);
if(idx<0){
sw = 1;
break;
}
}
i = row+1-z;
if(sw)break;
for(j=col-z+1;j>=z+1;j--){
mp[i][j] = idx--;
// printf("mp[%d][%d]=%d\\n",i,j,idx+1);
if(idx<0){
sw = 1;
break;
}
}
j = z;
if(sw)break;
for(i=row-z+1;i>=z+1;i--){
mp[i][j] = idx--;
// printf("mp[%d][%d]=%d\\n",i,j,idx+1);
if(idx<0){
sw = 1;
break;
}
}
}
至于i和j的起止到底是多少,我也不能一下子想出,但我知道肯定有对称性,于是试了出来(通过被注释掉的打印)
特别说明一下变量sw,是stop while的缩写,用于跳出while循环,且每次进入for循环之前都要判断一下sw是否为true。idx<0说明矩阵已填满。
1)每次idx--之后都判断一下idx是否<0,但是此时break,只能跳出内层for循环,要跳出外层循环还要借助sw变量。
2)何时判断sw呢?我们希望达到的效果是idx<0一旦成立,就不再填充,如果只是在刚进入while循环的时候判断一下,可能出现的情况是,在第三个for循环中断后,又进入第四个for循环,所以每次进入循环前都要判断一下sw。
但是这样做,有两个测试用例是运行超时的。我迫切地翻开参考书,想看看自己究竟哪里代码不优雅了。
1)那个sw的判断希望下次不要再看到了。直接把idx>=0放在while和for的括号里不香吗?理论上while可以不放,但是这样光标一直闪,程序会出问题。改进后如下
int idx = n-1,i,j,z=1;
for(z=1;idx>=0;z++){
i = z;
for(j=z;j<=col-z&&idx>=0;j++){
mp[i][j] = idx--;
}
j = col+1-z;
for(i=z;i<=row-z&&idx>=0;i++){
mp[i][j] = idx--;
}
i = row+1-z;
for(j=col-z+1;j>=z+1&&idx>=0;j--){
mp[i][j] = idx--;
}
j = z;
for(i=row-z+1;i>=z+1&&idx>=0;i--){
mp[i][j] = idx--;
}
}
代码清爽了很多,但是超时的问题仍毫无进展。
超时点1
2)我听参考书的话,加入了如下特判
if(n==1){
printf("%d",a[0]);
return 0;
}
于是从21变成了22分,有一个测试用例通过了。还剩一个超时,并且我注意到,刚才的两个超时,显示的时间都是-,也许是陷入了某种死循环。
3)我尝试提取i和j的边界中的公因子,引入
int r = col-z;
int d = row-z;
矩阵填充代码变成如下
int idx = n-1,i,j,z=1;
for(z=1;idx>=0;z++){
i = z;
int r = col-z;
int d = row-z;
for(j=z;j<=r&&idx>=0;j++){
mp[i][j] = idx--;
}
j = r+1;
for(i=z;i<=d&&idx>=0;i++){
mp[i][j] = idx--;
}
i = d+1;
for(j=r+1;j>=z+1&&idx>=0;j--){
mp[i][j] = idx--;
}
j = z;
for(i=d+1;i>=z+1&&idx>=0;i--){
mp[i][j] = idx--;
}
}
很遗憾,那个测试用例还是没过
4)最后,我又找出自己的代码和参考书代码的一个区别,那就是我在填充过程中填充的是数组下标,而参考书直接填充的内容,这样输出的时候就不必先映射到下标再输出,于是我照做。
将所有的
mp[i][j] = idx--;
改成了
mp[i][j] = a[idx--];
于是输出时候的
int idx = mp[i][j];
printf("%d",a[idx]);
也就自然变成了
printf("%d",mp[i][j]);
还是超时。。
超时点2
5)最后,我又发现,程序对最内层只有一个数字的情况进行了特判,也就是在4个for循环后加入了如下代码
i++;
j++;
if(idx==0)mp[i][j] = a[idx--];
好了,AC。
完整代码如下
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<map>
#include<string>
#include<stdlib.h>
using namespace std;
const int maxn = 10010;
int mp[200][200] = {0};
int main(){
int n;
int a[maxn];
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
if(n==1){
printf("%d",a[0]);
return 0;
}
int col,row;
for(int i=(int)sqrt(n);i>=1;i--){
if(n%i==0){
col = i;
break;
}
}
row = n/col;//row>=col
//a按照升序排好
sort(a,a+n);
int idx = n-1,i,j,z;
for(z=1;idx>=0;z++){
int r = col-z;
int d = row-z;
for(i=z,j=z;j<=r&&idx>=0;j++){
mp[i][j] = a[idx--];
}
for(i=z,j=r+1;i<=d&&idx>=0;i++){
mp[i][j] = a[idx--];
}
for(i=d+1,j=r+1;j>=z+1&&idx>=0;j--){
mp[i][j] = a[idx--];
}
for(i=d+1,j=z;i>=z+1&&idx>=0;i--){
mp[i][j] = a[idx--];
}
i++;
j++;
if(idx==0)mp[i][j] = a[idx--];
}
for(int i=1;i<=row;i++){
for(int j=1;j<=col;j++){
printf("%d",mp[i][j]);
if(j!=col)printf(" ");
}
printf("\\n");
}
return 0;
}
以上是关于1105 Spiral Matrix 给定数组向螺旋矩阵中填入数据的主要内容,如果未能解决你的问题,请参考以下文章