##PAT乙级真题 1038统计同成绩学生
本题要求读入 N 名学生的成绩,将获得某一给定分数的学生人数输出。
输入格式:
输入在第 1 行给出不超过 10
5
的正整数 N,即学生总人数。随后一行给出 N 名学生的百分制整数成绩,中间以空格分隔。最后一行给出要查询的分数个数 K(不超过 N 的正整数),随后是 K 个分数,中间以空格分隔。
输出格式:
在一行中按查询顺序给出得分等于指定分数的学生人数,中间以空格分隔,但行末不得有多余空格。
输入样例:
10
60 75 90 55 75 99 82 90 75 50
3 75 90 88
输出样例:
3 2 0
本题思路比较简单,可能出问题的就是最后一个测试点咯,嘎嗝我一开始也没过┭┮﹏┭┮
- 因为题给数据规模了,n<=100000,然后k跟n个规模一样喔。
- 所以用二重循环遍历就会超时了呀,O(nn)大概是100000100000一佰亿了~~~
- 思路:可以用数组,也可以用容器,我是用的数组哈。我先是将待查找的数组进行排序了,复杂度O(nlogn),然后k大小那个数组不要动,处理不好有可能影响输出顺序。对k大小的数组遍历,寻找每个元素在待查找的数组(已排序)的地方查找。(此时也不能用二重循环,不然又是O(n*n)了)。我想到的是进行二分查找O(logn).那么问题又来了,二分查找只查了一个,简单:(查到后,从mid那里分别往左往右再查呀,目测复杂度O(1),最后返回查到的个数.实在不明白可以看代码!最后还有总结哦 ,gu~~~lululu)
#include <iostream>
#include <algorithm>
using namespace std;
struct cnt
{
int data;
int cnt;
};
int Binsearch(int *grade,int low,int high,int x)
{
int cnt =0;
int mid;
while(low<=high)
{
mid = (high+low)/2;
if(grade[mid]==x) //核心core ,如果查到就往下看咯
{
for(int i=mid;grade[i]==x&&i>=low;i--) //从mid往左查
cnt++;
for(int i = mid+1;grade[i]==x&&i<=high;i++)//从mid+1往右查
cnt++;
return cnt;//最后就返回了,啥也不做咯,结束此次查找
}
else if(grade[mid]>x)
high = mid-1;
else if(grade[mid]<x)
low = mid+1;
}
return cnt;//否则就返回0
}
int main()
{
int n,k;
cin>>n;
int grade[100005];//用数组存储
for(int i=1;i<=n;i++)
cin>>grade[i];
cin>>k;
cnt ji[100005];
for(int i=0;i<k;i++)
{
int x;
cin>>x;
ji[i].data = x;
ji[i].cnt=0;
}
sort(grade+1,grade+1+n); //排序 O(nlogn)
for(int i=0;i<k;i++)
ji[i].cnt = Binsearch(grade,1,n,ji[i].data);//进行二分查找,很重要的一步
for(int i=0;i<k;i++) //最后的输出没毛病~~
{
if(i!=k-1)
cout<<ji[i].cnt<<" ";
else
cout<<ji[i].cnt;
}
return 0;
}
思路总结:
1.第一步将待查找的数组排序(O(nlogn))
2.第二步依次二分查找(O(nlogn))
3.当然就是输出啦
总复杂度O(nlogn),所以就不会超时啦。
以后碰到超时,就要考虑下是不是需要改进自己的算法啦