本题要求读入N名学生的成绩,将获得某一给定分数的学生人数输出。
输入格式:
输入在第1行给出不超过105的正整数N,即学生总人数。随后1行给出N名学生的百分制整数成绩,中间以空格分隔。最后1行给出要查询的分数个数K(不超过N的正整数),随后是K个分数,中间以空格分隔。
输出格式:
在一行中按查询顺序给出得分等于指定分数的学生人数,中间以空格分隔,但行末不得有多余空格。
输入样例:10 60 75 90 55 75 99 82 90 75 50 3 75 90 88输出样例:
3 2 0
算法:
- 算法开始。
- 读入N,N个成绩,要查询分数数量K,K个要查询的成绩。
- 用qsort对N个成绩进行降序排序。
- 查询第i个成绩,如果i不小于K,则跳到第十六步。
- 如果begin大于等于end,则跳到第十五步。
- 如果begin上的成绩大于要查询的成绩,end上的成绩小于要查询的成绩,进行下一步,否则跳到第十一步。
- middle=(begin+end)/2。
- 如果middle上的成绩大于要查询的成绩,则begin=middle-1,跳回第五步。
- 如果middle上的成绩小于要查询的成绩,则end=middle+1,跳回第五步。
- 如果middle上的成绩等于要查询的成绩,则middle一直加一,直到middle上的成绩小于要查询的成绩或者middle等于N-1,将middle赋值给tmp。跳到第十三步。
- 如果begin上的成绩等于要查询的成绩,则begin一直加一,直到begin上的成绩小于要查询的成绩或者begin等于N-1,将begin赋值给tmp,跳到第十三步。
- 如果end上的成绩等于要查询的成绩,则end一直加一,知道end上的成绩小于要查询的成绩或者end等于N-1,将end赋值给tmp,跳到第十三步。
- 如果tmp上的成绩小于要查询的成绩则tmp减一。
- 如果tmp上的成绩不大于要查询的成绩而且tmp不小于零,count加一,tmp减一。
- i加一,回到第四步。
- 输出每个要查询成绩的count。
- 算法结束。
#include <stdio.h>
#include <stdlib.h>
int cmp(const void* v1, const void* v2);
int main(void) {
int n, k, i, begin, end, middle, tmp, flag;
int* grades;
int* search;
int* count;
scanf_s("%d", &n);
grades = (int*)calloc(n, sizeof(int));
for (i = 0; i < n; i++) {
scanf_s("%d", grades + i);
}
scanf_s("%d", &k);
search = (int*)calloc(k, sizeof(int));
count = (int*)calloc(k, sizeof(int));
for (i = 0; i < k; i++) {
scanf_s("%d", search + i);
}
qsort(grades, n, sizeof(int), cmp);
for (i = 0; i < k; i++) {
begin = 0;
end = n - 1;
flag = 0;
do {
if (grades[begin] == search[i]) {
while ((grades[begin] == search[i])&&(begin < n)) {
begin++;
}
tmp = begin;
flag = 1;
break;
}
else if (grades[end] == search[i]) {
while ((grades[end] == search[i]) && (end < n)) {
end++;
}
tmp = end;
flag = 1;
break;
}
middle = (begin + end) / 2;
if (grades[middle] == search[i]) {
while (grades[middle] == search[i] && middle < n) {
middle++;
}
tmp = middle;
flag = 1;
break;
}
else if (grades[middle] > search[i]) {
begin = middle + 1;
}
else if (grades[middle] < search[i]) {
end = middle - 1;
}
} while (begin < end);
if (flag) {
if (grades[tmp] < search[i]) {
tmp--;
}
while (grades[tmp] == search[i]) {
tmp--;
count[i]++;
}
}
}
for (i = 0; i < k; i++) {
printf("%d", count[i]);
if (i != k - 1) {
putchar(' ');
}
}
free(grades);
free(count);
free(search);
return 0;
}
int cmp(const void* v1, const void* v2) {
return *((int*)v2) - *((int*)v1);
}
但是这个算法尽管运用了qsort和二分查找法,但是时间复杂度达到了O(nlogn),最后个测试点运行超时了。
下面来个专门解决问题的算法。
- 算法开始。
- 读入N。
- 每读入一个成绩i,就对grades[i]加一。
- 读入K。
- 每读入一个成绩i,就输出grades[i]。如果i不等于K-1,就输出一个空格。
- 算法结束。
是个方法时间复杂度只有O(n)。下列代码编写于VS2015,若要在PAT上运行,修改sanf_s即可。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int* grades;
int n, k, i, tmp;
scanf_s("%d", &n);
grades = (int*)calloc(101, sizeof(int));
for (i = 0; i < n; i++) {
scanf_s("%d", &tmp);
grades[tmp]++;
}
scanf_s("%d", &k);
for (i = 0; i < k; i++) {
scanf_s("%d", &tmp);
printf("%d", grades[tmp]);
i != k - 1 ? putchar(' '):putchar('\0');//i != k - 1 ? putchar(' '):putchar(NULL); 这样也对。
}
free(grades);
return 0;
}