您的位置:首页 > 其它

1038. 统计同成绩学生

2016-02-21 08:27 253 查看
本题要求读入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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: