1038. 統計同成績學生
阿新 • • 發佈:2019-01-28
本題要求讀入N名學生的成績,將獲得某一給定分數的學生人數輸出。
但是這個演算法儘管運用了qsort和二分查詢法,但是時間複雜度達到了O(nlogn),最後個測試點執行超時了。 下面來個專門解決問題的演算法。
輸入格式:
輸入在第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,就輸出一個空格。
- 演算法結束。
#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;
}