马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 zhangjinxuan 于 2022-8-30 16:15 编辑
鱼油们应该刷过oj吧!刷oj时,自信满满的提交,却被一个WA狠狠打脸
有时他也是TLE,RE,分别是超时,运行时错误 的意思,说明你程序的执行效率有亿点点逊...
如何提高执行效率呢?就看以下5条你中招没!
1.memset是一个very good的函数,但他应该用到该用的地方,什么意思呢?看这个代码:#include <bits/stdc++.h>
using namespace std;
int a[100000];
int main()
{
memset(a,0,sizeof(a));
//...
}
memset是一个O(n)的函数,那么程序的时间复杂度应是O(n)
但,可以优化吗?
当然可以!把memset这一行去掉即可!
为什么呢?因为本程序的memset的第二个参数是0,没有初始化为0的必要
因为 全局变量默认初始化为0!
但是如果你要初始化其他值的话,就加上吧,或者用别的方法...
2.看看哪个快?//test1.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
for (int i=0;i<1e9;++i)
{
for (int j=0;j<5;++j)
1+1==2;
}
}
//test2.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
for (int i=0;i<1e9;++i)
{
1+1==2;
1+1==2;
1+1==2;
1+1==2;
1+1==2;
}
}
乍一看,2个代码都是执行5e9次1+1==2,应该都一样吧,但事实并非如此,我们写个测试程序试一试:#include <bits/stdc++.h>
using namespace std;
int main(){
double st=clock();
for (int i=0;i<1e9;++i)
{
for (int j=0;j<5;++j)
1+1==2;
}
double en=clock();
printf("test1:%.2f\n",en-st);
st=clock();
for (int i=0;i<1e9;++i)
{
1+1==2;
1+1==2;
1+1==2;
1+1==2;
1+1==2;
}
en=clock();
printf("test2:%.2f\n",en-st);
}
结果竟然出乎意料的打印了不同的值(毫秒为单位):
test1:4914.00 (4.914秒)
test2:1616.00 (1.616秒)
为什么同样的功能,差异为何如此之大?
因为一个for循环它有许多"多余"的操作,比如开始初始变量,循环一次判断条件,又更新计数器变量,那得多慢!
所以,当循环次数已知并且比较小,推荐使用类似程序2的写法
3.再来看看哪个快?#include <bits/stdc++.h>
using namespace std;
struct test{
long double c[30],a;
long long b[100];
}ar[300000];
bool cmp1(test a,test b){return a.a>b.a;}
bool cmp2(test &a,test &b){return a.a>b.a;}
int main(){
int st=clock();
sort(ar,ar+300000,cmp1); //这个快?
int en=clock();
printf("test1:%d\n",en-st);
st=clock();
sort(ar,ar+300000,cmp2); //还是这个快?
en=clock();
printf("test2:%d\n",en-st);
}
输出:
test1:1184
test2:654
为什么?cmp2仅仅就是加了两个&,两个程序的差距竟这么大??!
仔细看看,test结构体有一个long double的数组,一个long long的数组,外加一个long double的a,其大小可想而知(内存逊的鱼油们不要轻易尝试!)
其实学过引用函数的都知道,参数加上&,就变成了引用,传过去的是变量的地址,而地址的大小仅仅就是4字节或8字节,比test结构体少好多倍
那有的鱼油就问了:参数很大很小关执行效率有什么关系捏?
其实不然,如果一个函数的参数的大小很大,那么整个函数的开销就很大,所以当参数很大时,建议加上引用或者指针
4.cin vs scanf
学过C++的应该都用过cin
但cin的效率高不高呢?
答:很低,比你想象的还低。有一次做题,用scanf很nice的AC了,但改为cin就奇妙的TLE了
还是不信?那再写个测试程序!#include <bits/stdc++.h>
using namespace std;
int main(){
freopen("test1.out","r",stdin);
int st=clock();
char tmp[20];
for (int i=0;i<1000000;++i)scanf("%s",tmp);
int en=clock();
fprintf(stderr,"test1:%d\n",en-st);
st=clock();
freopen("test2.out","r",stdin);
for (int i=0;i<1000000;++i)
cin>>tmp;
en=clock();
fprintf(stderr,"test2:%d\n",en-st);
}
程序输出:(假设test2和test1里面都是1000000行的IloveFichc.com)
test1:497
test2:719
所以:勤用scanf,少用cin
不过对于printf与cout的测试我这边竟然是cout比printf快十多倍,不知道是什么原因,所以不敢乱说,感兴趣的鱼油可以试一试或查一查
5.之前讲过函数的开销取决于参数,它也取决于函数体,什么意思呢?看代码:#include <bits/stdc++.h>
using namespace std;
int main(){
int a[1000000];
}
写过类似的都知道,他在linux中会提示 段错误(吐核)之类的,而在windows中返回错误码:3221225725 这种就是RE
其实这是栈溢出,一个函数,运行时会加入到系统分配的栈里面,如果一个函数的开销很大,那么栈的空间就不足了,从而产生栈溢出
有解决方法吗?依然写出来了,当然有!
方法一:static int a[MAXN]; 使用静态数组,这样不会栈溢出(具体啥原因俺也不知道)
方法二:使用stl容器
方法三:定义全局数组
6.不是说只有5条吗?怎么还有第6条?
那就是一个大问题了,我觉得灰常多萌新会犯这个错误的...
如果有帮助那就 回帖!顶!加评分!嘻嘻~ 这就是第6条~
[本文为本萌新原创,为个人经验,仅供学习使用,若有错误希望大佬指正,指正有鱼币奖励!] |