【python2C】算法基础:计时比较

news2024/9/20 11:11:03

不断改进代码,是学习进步必经之路。
判断代码优劣,在空间允许的情况下,计时就是最可靠的标尺。

打表不算,人脑不算

1.对于答案较为固定的题,预先算出所有可能的答案表,然后对应输入查找答案,从而获得一个满足题目要求速度的AC,当然不能算是出题者想要的解决方案。
2.用过于复杂的逻辑、或者较多较难的数理推导,过于依赖人脑代替电脑,显然是失去了算法竞赛的初衷,也可能耗费过多的比赛时间。(天才随意)

计时:时间戳之差

通过获取运行时的时间戳,对比一段代码运行前后的时间戳之差,来作为运行效率的比较。
但时间戳可能受各种条件影响而产生波动。
一般通过增加数据规模,或者多次重复累加/平均,来获得一个较为稳定可靠的值。

获取时间戳,python最常用的是time模块的 time.time() 和time.perf_counter()方法
c++的ctime也有类似的方法,但更可靠的是 chrono的chrono::high_resolution_clock::now()方法

python的time类

可以通过 dir(time)和help()自行查询学习
获取时间戳的方法主要有两类:(‌纪元时间Epoch指的是1970年1月1日00:00:00 UTC。)

python time类的时间戳方法
方法说明示例sleep
time返回以秒为单位的浮点数,从Epoch至今.time() -> float
perf_counter返回以秒为单位的浮点数,基准时间,最高精度.perf_counter() -> float
monotonic返回以秒为单位的浮点数,精度稍差但单调递增.monotonic() -> float
process_time返回当前进程的系统和用户CPU时间总和的秒数.process_time() -> float
X_ns返回以纳秒为单位的整数,X对应以上各种time.time_ns() -> int/

其他方法还包括thread_time()用于同一线程之间的时差计算。

此外,还有timeit模块用于重复测试

C++的chrono库

python本来就是用c++写的,所以对应的方法必须都有。
详细的超级水文见std::chrono库使用说明

简单一句话,测试csp赛的代码,用 std::chrono::high_resolution_clock::now()就好了

# include <bits/stdc++.h>
using namespace std;
using namespace std::chrono;

// ...

auto start=high_resolution_clock::now(); 

// do sth.

auto end=high_resolution_clock::now();
auto dt=duration_cast<milliseconds>(end - start).count();

cout<<dt<<" ms"<<endl;

一个例子

比较两种获得不超过n位的回文数的算法

# include <bits/stdc++.h>
using namespace std;
using namespace std::chrono;

int mkHW(int HW[],int n){//获得n位的奇回文数
	auto start=high_resolution_clock::now(); 
	// n为奇数,且首末位为奇数
	int cnt=0;
	long long d[(n+1)/2]={1}; if(n>=3)d[1]=101; 
	for(int i=2;i<(n+1)/2;i++)d[i]=d[i-1]*100-99;
	// 1位 
	for(int i=1;i<10;i+=2)	HW[cnt++]=i; if(n==1) return cnt;
	// 2位 
	HW[cnt++]=11; if(n==2) return cnt;
	// 3位 
	int iS=cnt,j=1; //iS预存3位的起点 
	for(int i=1;i<10;i+=2)for(int k=0;k<10;k++)HW[cnt++]=i*d[j]+k*10; 
	if(n==3) return cnt;
	// 5位
	int iE=cnt;j=2; //iE预存3位的终点,不包括iE
	for(int i=1;i<10;i+=2)
		for(int k=0;k<10;k++)
			for(int ii=iS;ii<(iE-iS)/5+iS;ii++) 
				HW[cnt++]=i*d[j]+k*d[j-1]*10+(HW[ii]%d[j-1])*10;
	if(n==5) return cnt;
	// n位
	for(j=3;j<(n+1)/2;j++){
		iS=iE;iE=cnt; // 上上轮的终点即为上轮的起点
		for(int i=1;i<10;i+=2)
			for(int k=0;k<10;k++)
				for(int ii=iS;ii<(iE-iS)/5+iS;ii++)  
					HW[cnt++]=i*d[j]+k*d[j-1]*10+(HW[ii]%d[j-1])*10;
	}
//	for(int i=0;i<cnt;i++)cout<<HW[i]<<" "; cout<<endl;
	auto end=high_resolution_clock::now();
	auto dt=duration_cast<nanoseconds>(end - start).count();
	cout<<"in func mkHW : "<<dt<<" ns"<<endl;
	return cnt;
}
bool isHW(int x){
    int x2=x,y=0; 
    while(x2!=0){y=y*10+x2%10;x2/=10;} 
    return x==y;
} 
int main(){
//	int n;cin>>n;
//	long long m; m=pow(10,n);
	int m=9999999,sq=int(sqrt(m*100))+1;
	int hw[sq];cout<<sq<<endl;
	
	// test for all 回文 
	auto start=high_resolution_clock::now(); 
	int cnt=0;for(int i=0;i<m;i++)if(isHW(i))hw[cnt++]=i;
	auto end=high_resolution_clock::now();
	auto d=duration_cast<nanoseconds>(end - start).count();
	cout<<"test 1 : "<<cnt<<" : "<<d<<" ns"<<endl;
//	for(int i=0;i<cnt;i++)cout<<hw[i]<<" "; cout<<endl;
	
	// test for odd 奇数回文 
	start=high_resolution_clock::now(); 
	cnt=0;
	int x2=m,n=0;while(x2!=0){n++;x2/=10;}
	cnt=mkHW(hw,n); 
	end=high_resolution_clock::now();
	d=duration_cast<nanoseconds>(end - start).count();
	cout<<"test 2 : "<<cnt<<" : "<<d<<" ns"<<endl; 
//	for(int i=0;i<cnt;i++)cout<<hw[i]<<" "; cout<<endl;

 	return 0;
}

明显可以看到创造比暴力遍历耗时要少很多,当然也麻烦些。(遍历比通过字符串转换快,那个根本运行不了这数据规模)

需要说明的是,有时测试时间会为0,后来发现是内存溢出或者其他各种隐形的错误的影响,修正后就正常了。
但我这个函数mkHW里的计时器,为什么一直都是0呢? 但又查不出错。
有没有哪位好心人在评论里留言或者私信的?感谢!
 

好吧,其实用 steady_clock 代替 high_resolution_clock 就正常了

所以是不是首选 std::steady_clock::now() 呢?
期待评论里留言或者私信交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2123744.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【OpenGL 002】着色器 GLSL 语言及GLFW代码案例

文章目录 1.GLSL语言简介本节案例 code 1 2.GLSL的数据类型① 向量(Vector)- 向量重组示例- 向量重组禁忌 3.GLSL的输入输出本节案例 code 2 4.着色器示例5.Uniform本节案例 code 3 通过第一节 【OpenGL 001】Ubuntu 搭建 GLFW 环境及其相关测试 demo 想必已经搭建好了GLFW环境…

『功能项目』GameObject对象池 - 第三职业【39】

本章项目成果展示 我们打开上一篇38管理器基类的项目&#xff0c; 本章要做的事情是利用对象池制作第三个职业——魔法师 在GameRoot对象下创建空物体 重命名为PoolRoot 将GameRoot拖拽至预制体 创建脚本&#xff1a; 编写脚本&#xff1a;PoolManager.cs using UnityEngine;…

使用豆包MarsCode 编写 Node.js 全栈应用开发实践

以下是「豆包MarsCode 体验官」优秀文章&#xff0c;作者狼叔。 欢迎更多用户使用豆包MarsCode 并分享您的产品使用心得及反馈、创意项目开发等&#xff0c;【有奖征集&#xff5c;人人都是豆包MarsCode 测评官&#xff01;】活动正在火热进行中&#xff0c;欢迎大家投稿参加&a…

【Python报错已解决】 SyntaxError: invalid syntax

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;修复缺失的括号或引号2.…

甘肃五仁月饼:传统风味,舌尖上的乡愁

在中秋佳节的美食画卷中&#xff0c;甘肃食家巷五仁月饼以其独特的魅力占据着重要的一席之地。甘肃五仁月饼&#xff0c;那朴实无华的外表下&#xff0c;藏着无尽的美味与情怀。它的饼皮金黄酥脆&#xff0c;散发着淡淡的麦香&#xff0c;仿佛在诉说着古老的制作工艺。轻轻咬上…

Java:动态代理

Java&#xff1a;动态代理 什么是代理 代理模式 是一种设计模式&#xff0c;它为其他对象提供了一种代理以控制对这个对象的访问。代理对象通常包装实际的目标对象&#xff0c;以提供一些附加的功能&#xff08;如延迟加载、访问控制、日志记录等&#xff09;。我们一般可以使…

C++中的内存管理和模板初识

一、内存管理 1.1内存区域的划分 1.1.1内存划分区域图示 1.1.1补&#xff1a;堆和栈都可以进行动态分配和静态分配吗&#xff1f; 不是的&#xff0c;堆无法进行静态分配&#xff0c;只能动态分配&#xff1b;栈可以利用_alloca动态分配&#xff0c;但是分配的空间不能用fre…

基于Logistic-Map混沌序列的数字信息加解密算法matlab仿真,支持对文字,灰度图,彩色图,语音进行加解密

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于Logistic-Map混沌序列的数字信息加解密算法matlab仿真,系统包含GUI操作界面&#xff0c;系统支持对文字,灰度图,彩色图,语音进行加解密。 2.测试软件版本以及…

项目运行插件-日志管理

日志管理 项目运行时模块提供了项目日志收集&#xff0c;检索和保存查询方案等功能。 体验地址&#xff1a; http://119.163.197.219:13456/view/runtime/index.html#/log/aioLogPage 沟通加QQ群 &#xff1a; 908377977 gitee 开源地址 &#xff1a; https://gitee.com/aio…

打印文档时,只有图片中的文本不清晰该如何处理

最近打印东西的时候&#xff0c;发现只有图片中的文本并不清晰&#xff0c;就想研究一下如何改善这个问题。 打印机是佳能的 MF113w&#xff0c;一个不错的多功能激光黑白打印机&#xff0c;支持无线打印。唯一问题就是每次 DHCP 分配 IP 到期后&#xff0c;这款打印机就会亮错…

AI提质增效率赋能工业产品质检,基于高精度YOLOv5全系列参数【n/s/m/l/x】模型开发构建工业生产场景下PCB电路板缺陷问题智能化分割检测识别分析系统

在PCB电路板的生产制造过程中&#xff0c;质量检测是确保产品质量、维护品牌形象的关键环节。然而&#xff0c;传统的人工检测方式依赖于经验丰富的工人师傅通过光学显微镜等设备进行逐块检查&#xff0c;这不仅劳动强度大、效率低下&#xff0c;而且受限于人的主观判断、视力疲…

《华为 eNSP 模拟器安装教程》

1.电脑安装环境要求&#xff1a; 检查电脑是否安装过 eNSP 和依赖软件&#xff0c;如果有&#xff0c;请全部卸载。 安装软件列表&#xff1a; 2.软件安装&#xff1a; 安装 WinPcap&#xff1a; 打开安装包&#xff0c;单击【Next】 单击【I Agree】 单击【Install】 单击【…

《信息系统安全》课程实验指导

第1关&#xff1a;实验一&#xff1a;古典密码算法---代换技术 任务描述 本关任务&#xff1a;了解古典密码体制技术中的代换技术&#xff0c;并编程实现代换密码的加解密功能。 注意所有明文字符为26个小写字母&#xff0c;也就是说字母表为26个小写字母。 相关知识 为了完…

1、常用的数据库、表操作

基本的建表和数据库拷贝操作。 一、数据定义语言DDL show databases; # 查看全部数据库 show create database db; # 查看数据库db create database db; # 创建数据库db drop database db; # 删除数据库db use db; # 使用数据库db基本…

1 Linux SSH安全加固_linux system-auth

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201117150524918.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center) ![在这里插入图片描述](https://…

11、LLaMA-Factory自定义数据集微调

1、数据集定义 针对实际的微调需求&#xff0c;使用专门针对业务垂直领域的私有数据进行大模型微调才是我们需要做的。因此&#xff0c;我们需要探讨如何在LLaMA-Factory项目及上述创建的微调流程中引入自定义数据集进行微调。**对于LLaMA-Factory项目&#xff0c;目前仅支持两…

什么是 Grafana?

什么是 Grafana&#xff1f; Grafana 是一个功能强大的开源平台&#xff0c;用于创建、查看、查询和分析来自多个来源的数据。通过可视化仪表盘&#xff08;Dashboard&#xff09;&#xff0c;它能够帮助用户监控实时数据、生成历史报告&#xff0c;甚至进行预测分析。Grafana…

深入理解Java虚拟机:Jvm总结-类文件结构以及类加载机制

第六章 类文件结构 6.1 意义 代码编译的结果从本地机器码转变为字节码&#xff0c;冲破了平台界限。 6.2 无关性的基石 实现语言无关性的基础仍然是虚拟机和字节码存储格式。Java虚拟机不与包括Java语言在内的任何程序语言绑定&#xff0c;它只与“Class文件”这种特定的二…

vue2实践:el-table实现由用户自己添加删除行数的动态表格

需求 项目中需要提供一个动态表单&#xff0c;如图&#xff1a; 当我点击添加时&#xff0c;便添加一行&#xff1b;点击右边的删除时&#xff0c;便删除这一行。 至少要有一行数据&#xff0c;但是没有上限。 思路 这种每一行的数据固定&#xff0c;但是不定行数的&#x…

校园水电费管理|基于java的校园水电费管理小程序系统 (源码+数据库+文档)

校园水电费管理 目录 基于java的校园水电费管理小程序系统 一、前言 二、系统设计 三、系统功能设计 小程序端 后台功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕…