分析

本体思路很简单:读入数据,排序、统计、输出。难点在于数据量较大,选择何种排序方法就极为重要,否则很容易发生内存或时间超限。可以考虑以下几种思路:

  1. 桶排序

    桶排序是可以想到的最简单方法,可在O(n)的时间内一次性完成排序和统计:tong[number]++;,考虑到本题中被统计的数字的范围0~1.5*10^9,就需要至少1.5*10^9大小的桶,这样大的一个int数组所占用的内存空间为6*10^9字节(32位计算机中一个int为4个字节),即6G Byte,已经远远超了128M Byte的要求,故桶排序无法使用。

  2. 冒泡排序

    冒泡排序是最简单的一种稳定性排序,时间复杂度为O(n2)。可以考虑将所有的数据读入一个数组中再进行排序、统计。根据题目已知n的范围:1~200000,按最坏情况考虑,O(n^2)=2*10^10,单核心CPU时钟频率数量级一般为GHz,即1s可以执行1*10^9条指令(这里仅为数量级上的估算,不同型号CPU在不同计算机系统下的具体计算速度是不一样的)。可见使用冒泡排序很难在1s内完成排序,需要更高效的排序方法。

  3. 插入排序

    插入排序的时间复杂度也是O(n2),但考虑这样一种情况,因为不相同的数字不超过10000个,对于已经存在的数字,我们简单的对其计数,对于不存在的数字,进行插入排序。具体分析如下:

    • 对于不相同的数字,最多进行10000个插入操作,相当于10000个数字进行插入排序,所需时间为1*10^8,这是CPU在1s内能够完成的。
    • 对于相同的数字,因为已经存在,只需要将其找出,并对其计数加1,如果使用顺程序查找的话,时间复杂度为O(n),在10000个数字里面查找一个数字,最坏情况选需要10000次,那么在最糟糕情况下:统计200000个数字,其中有10000次为插入&排序操作,190000次为查找计数操作,这190000次消耗时间最多为190000*10000=1.9*10^9,远超CPU单位时间(1s)内的运算能力。为了减少这部分时间,考虑到我们是在一个已拍好序的序列中查找,因此可以使用折半查找,每次查找的次数最多为log10000,最多14次,那么190000次查询消耗时间最多为190000*14=2.66*10^6,耗时最够低,满足我们的要求。
    • 算法思路如下:
      1. 初始化count=0,序列NUM[10001][2]={0};
      2. 读入一个数字number
      3. 在序列NUM中查找这个number并返回位置wz
      4. 如果wz==-1(不存在),将number以插入排序方式插入序列,count++
      5. 如果wz>0(存在),则该位置计数加1,NUM[wz][1]++;
      6. 返回第2步

该思路是在一边插入、一边排序、一边统计,代码见例程1。

  1. 快速排序

    快速排序是一种很高效的排序方法:时间复杂度为nlogn,将n个数字进行排序的话最大时间为200000*log200000,约为3.6*10^6,可见效率极高,当然这个数字是最理想情况了,实际情况差点,但在数量级上一般不会差异过大。这里不再详细分析快速排序,可参考输油管道问题。代码见例程2。

  2. 使用algorithm算法库

    如果允许使用algorithm算法库,问题就更简单了,直接使用sort函数,有人问这个sort函数使用了什么算法,这就复杂了:STL中的sort在普通快速排序的基础上进行了优化,它还结合了插入排序和堆排序。根据不同的数量级别以及不同情况,能自动选用合适的排序方法。当数据量较大时采用快速排序,分段递归。一旦分段后的数据量小于某个阀值,为避免递归调用带来过大的额外负荷,便会改用插入排序。而如果递归层次过深,有出现最坏情况的倾向,还会改用堆排序。晕了吧?要知道,C++中的STL模板库可都是聪明人写出来的……不打击你了,感兴趣的话,自己去下载STL的源代码学习学习吧,本题使用sort的代码见例程3。

例程1:插入排序和二分查找

#include<iostream>
using namespace std; int a[10001][2]; //存储序列,a[i][0]为数字,a[i][1]为计数
int count=0; //存储序列中的数字个数 int find(int num){ //二分查找
int low=1, high=count, middle;
while(low<=high){
middle=(low+high)/2;
if(a[middle][0]==num) return middle;
if(num<a[middle][0]) high=middle-1;
if(num>a[middle][0]) low=middle+1;
}
return -1; //-1为未找到
} int main(){
int n;
scanf("%d", &n);
while(n>0){ //循环读入并处理n个数字
int num, wz; //num临时存放读入的数字,wz为t在a中的位置
scanf("%d", &num);
wz=find(num);
if(wz==-1){ //t没找到,插入到a中
int pos=++count; //pos为新插入点值,作为哨兵进行插入排序
a[pos][0]=num;
a[pos][1]=1;
while(pos>1 && a[pos][0]<a[pos-1][0]){
int t=a[pos][0];
a[pos][0]=a[pos-1][0];
a[pos-1][0]=t;
t=a[pos][1];
a[pos][1]=a[pos-1][1];
a[pos-1][1]=t;
}
}else a[wz][1]++; //t找到了,计数加1
n--;
}
for(int i=1; i<=count; i++) //循环输出
printf("%d %d\n", a[i][0], a[i][1]);
return 0;
}

例程2:快速排序

#include<iostream>
using namespace std; int a[200001];
void qsort(int l, int r){
int i,j,m,p;
i=l; j=r; //i从左边开始找,j从右边开始找
m=a[(l+r)/2]; //m为枢轴
while (i<=j) //循环条件
{
while (a[i]<m) i++;
while (a[j]>m) j--;
if (i<=j)
{
p=a[i]; a[i]=a[j]; a[j]=p;
i++; j--;
}
}
if (i<r) qsort(i,r); //递归和终止条件
if (l<j) qsort(l,j); //递归和终止条件
} int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
qsort(1,n);
for (int i=1, count=0; i<=n; ++i){
count++; //累加计数
if((i==n) || (a[i]!=a[i+1])){ //如果是最后一个或者下个数字不等于当前数字
printf("%d %d\n",a[i], count); //输出
count=0; //count归0
}
}
return 0;
}

例程3:使用algorithm库中的sort算法

#include<iostream>
#include<algorithm>
using namespace std; int main(){
int n;
int a[200001];
scanf("%d",&n);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]); //从下标1开始存放
sort(a+1, a+n+1); //sort排序
for(int i=1,count=0; i<=n; ++i){
count++; //累加计数
if ((i==n) || (a[i]!=a[i+1])){ //如果是最后一个或者下个数字不等于当前数字
printf("%d %d\n",a[i], count); //输出
count=0; //sum归0
}
}
return 0;
}

LFYZ-OJ ID: 1015 统计数字(NOIP2007)的更多相关文章

  1. 统计数字noip2007

    7909:统计数字 总时间限制:  1000ms 内存限制:  65536kB 描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109).已知不相同的数不超过1000 ...

  2. 洛谷-统计数字-NOIP2007提高组复赛

    题目描述 Description 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照 ...

  3. 【9207&&b701】统计数字(NOIP2007)

    问题描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000 (1.5*109).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出 ...

  4. luogu1097统计数字[noip2007提高组Day1T1]

    题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出 ...

  5. NOIP2007 统计数字

    1.统计数字 (count.pas/c/cpp) [问题描述] 某次科研调查时得到了 n 个自然数,每个数均不超过 1500000000(1.5*109).已知不相同的数 不超过 10000 个,现在 ...

  6. 洛谷 P1097 统计数字

    P1097 统计数字 题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自 ...

  7. 【MFC】ID命名和数字约定

    ID命名和数字约定 MFC ID 命名和数字约定需要满足以下要求: 提供对 Visual C++ 资源编辑器支持的 MFC 库和 MFC 应用程序中使用的一致的 ID 命名标准. 这样就可以轻松地对程 ...

  8. lintcode 中等题:digits counts 统计数字

    题目 统计数字 计算数字k在0到n中的出现的次数,k可能是0~9的一个值 样例 例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现 ...

  9. 每日一练之排序算法(P1097 统计数字)

    某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5×10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果. ...

随机推荐

  1. SQLServer无法删除登录名'***',因为该用户当前正处于登录状态解决方法

    问题描述: sqlserver在删除登录名的时候提示删除失败 标题: Microsoft SQL Server Management Studio -------------------------- ...

  2. 3星|《给产品经理讲技术》:APP开发技术介绍,没有技术背景的话恐怕只能看懂书中的比喻和结论

    基本是APP开发涉及到的相关技术的入门级介绍.涉及到的知识点与技术细节比较多,不少技术相关的内容并没有像标题暗示的那样没有技术背景也可以看懂,而是涉及到许多专业的术语.原理.也有一些内容是用比喻的方法 ...

  3. 5.机器学习——DBSCAN聚类算法

    1.优缺点 优点: (1)聚类速度快且能够有效处理噪声点和发现任意形状的空间聚类: (2)与K-MEANS比较起来,不需要输入要划分的聚类个数: (3)聚类簇的形状没有偏倚: (4)可以在需要时输入过 ...

  4. QQ的孤独

    接触网络到现在,已是好多年前的事了.初识网络犹如初恋般,充满了新鲜和好奇,于是,从聊天室到QQ,MSN,邮箱,再去BBS.然后有了博客^^^^^^ 那时的网络于我是那般充满诱惑,整天穿梭其中,乐此不彼 ...

  5. Python进程池Pool

    ''' 进程池,启动一个进程就要克隆一份数据,假设父进程1G,那么启动进程开销很大 避免启动太多造成系统瘫痪,就有进程池,即同一时间允许的进程数量 ps:线程没有池,因为线程启动开销小,线程有类似信号 ...

  6. OpenCV 与 OpenGL 的关系是什么?

    OpenCV是 Open Source Computer Vision LibraryOpenGL是 Open Graphics LibraryOpenCV主要是提供图像处理和视频处理的基础算法库,还 ...

  7. C++笔记--thread pool【转】

    版权声明:转载著名出处 https://blog.csdn.net/gcola007/article/details/78750220 背景 刚粗略看完一遍c++ primer第五版,一直在找一些c+ ...

  8. Luogu4755 Beautiful Pair 最值分治、主席树

    传送门 整天做一些模板题感觉药丸 设\(val_i\)表示第\(i\)个位置的值 看到区间最大值考虑最值分治.对于当前的区间\([l,r]\),找到区间最大值\(mid\),递归\([l,mid-1] ...

  9. 开发工具IntelliJ IDEA的安装步骤及首次启动和创建项目

    开发工具IDEA概述 DEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量.它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公 ...

  10. SSH服务器拒绝了密码,请再试一次

    使用Xshell连接ubuntu后,出现: SSH服务器拒绝了密码,请再试一次! 输入: cd /etc/ssh/ 继续: vim sshd_config 若此时提示没有安装vim,那我们安装以下: ...