原题:
输入一些学生的分数,哪个分数出现的次数最多?如果有多个并列,从小到大输出。
任务1,分数为不超过100的非负整数。(题眼。)
任务2,分数为不超过100.00的非负实数。保留两位小数(两位的处理)
依照惯例,先看看我的垃圾代码。
#include此处为任务2的代码,任务1直接将a,c换成int型数组即可。#include #include int b[100];double a[100],c[100];int main(){ int i =0,flag,j,al,max=0,k=0,cl; double t; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); while(scanf("%lf",&t)==1) { flag=0; for(j=0;j max) { max=b[j]; memset(c,0,sizeof(c)); k=0; c[k++]=a[j]; } else if(b[j]==max) { c[k++]=a[j]; } break; } } if(!flag) { a[i]=t; b[i]=1; i++; } } al=i;//利用i来记录a的长度 不同数字的个数 cl=k;//c的长度 最多出现的数字的个数 //给c选择排序 for(i=0;i c[j]) { t=c[j]; c[j]=c[i]; c[i]=t; } } } printf("%d\n",al); for(i=0;i
此方法很弱智地绕弯型思维,竟然用了三个数组完成这件事,而且数组长度明显存在隐患。因为方法错误而产生了各种较为难以解决的问题。
此方法的思维模式是:
1.如何将输入的数字存起来,并且记录其出现的次数。
2.如何找到出现最多次的数字,并存起来。(此处需要动态重置数组)
3.如何排序
于是为了解决这三个问题,花费了非常复杂的代码。虽然见佛当佛见鬼杀鬼,但是在性能上明显输了。而且有缺点。
1.数组长度漏洞
2.doule型比较存在隐患
此时,再看看什么叫算法艺术。
int max=0,n=0,a[100]={0},x; while(cin >> x) { if(++a[x]>max) max=a[x]; if(x>n) n=x;//此处记录最大的分数,用来缩小循环次数 } for(int i=0;i<=n;i++) if(a[i]==max) cout << i << " ";多么简洁,多么完美,多么像一个清新可人的少女阿我去。。。
启发
1.数组下标本身就是一个有序数组,因为0~100,正好是题目中要求的范围,
此举(1) 解决了一个记录输入数据的数组,节省空间。(2)解决了排序的问题,直接按序输出,即可。
2.此代码简洁异常。比如++的利用,比如a[100]={0}的利用,不过这个貌似是才c++的特殊用法。c里是memset()
3.这才是直接型的思维。 你本来要输入未知个数个数据,但是这个数据的范围是有限的,而且你还要在这些数据上做文章。
那么用数组下标来表示数据,用数组内容来表示个数,极其合适。顺便解决了排序的问题
4.扩展性好,比如看任务2的代码。
int max=0,n=-1,a[10010]={0}; //is hash? double x; while(cin >> x){ if(++a[(int)floor(x*100)]>max) max=a[(int)floor(x*100+0.5)];// +0.5防止浮点数陷阱 if((int)floor(x*100)>n) n=(int)floor(x*100);//用来缩小循环次数 } for(int i=0;i<=n;i++) if(a[i]==max) printf("%.2lf ",(double)i/100); //cout << setiosflags(ios::fixed) << setprecision(2) << (double)i/100 << " ";接4. 因为要解决有关二位小数的问题,但是数组下标只能是整数。所以不妨用10000来表示100.00 用2233来表示22.33
简直完美。
今天才知道这个叫做桶排序
今天拿冒泡排序的代码去试wikioi的排序题。。。超时太严重了
在题解中了解到了,归并排序,,快速排序,希尔排序,等等还有c++的stl中的sort,貌似也不超时。
选择排序,是一种不稳定的排序,冒泡排序是一种稳定排序。。。我之前一直弄混了。