IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 1105 Spiral Matrix 给定数组向螺旋矩阵中填入数据 -> 正文阅读

[开发测试]1105 Spiral Matrix 给定数组向螺旋矩阵中填入数据

两个测试用例超时,可直接跳转到

目录

超时点1

超时点2


???????

要做的事情是,将数组按照非升序/降序,顺时针从外围到内部一圈一圈地把数据填到矩阵中,并打印出来。也就是将数组排好序后,将矩阵的坐标和数组的下标对应起来。

所以用一个这样的数组存放矩阵相应位置上元素的数组下标。

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;
}

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章           查看所有文章
加:2021-08-26 12:24:47  更:2021-08-26 12:27:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 22:26:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码