我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805348471259136
题目描述:
题目翻译:
1129 推荐系统
推荐系统预测用户对项目的偏好。现在要求你编写一个非常简单的推荐系统,该系统根据用户访问项目的次数对用户的偏好进行评级。
输入格式:
每个输入文件包含一个测试用例。对每个测试用例,第一行包含两个正整数:N(<= 50,000),代表查询总数,K(<= 10),代表系统可以向用户显示的最大推荐数。然后在第二行中给出用户正在访问的项目的索引——为了简单起见,所有项目都从1到N索引。一行中的所有数字用空格分隔。
输出格式:
对于每种情况,逐个处理查询。以下述格式分行输出查询的建议:
query: rec[1] rec[2] ... rec[K]
其中query是用户正在查询的项目,rec [i](i = 1,... K)是系统向用户推荐的第i个项目。最频繁访问的前K个项目应该以其频率的非递增顺序推荐。如果存在访问频率相等的情况,则按项目编号按递增顺序排序。
注意:第一项没有输出,因为当时无法提供任何建议。题目保证至少有一个查询的输出。
输入样例:
12 3
3 5 7 5 5 3 2 1 8 3 8 12
输出样例:
5: 3
7: 3 5
5: 3 5 7
5: 5 3 7
3: 5 3 7
2: 5 3 7
1: 5 3 2
8: 5 3 1
3: 5 3 1
8: 3 5 1
12: 3 5 8
知识点:set集合的应用
思路:用一个结构体保存出现的数字及其出现的次数
重载结构体的小于符号,利用set集合来自动排序。
每次更新set集合时,我们先要寻找set集合里是否有该数字及其出现次数,如果有,需要先将其erase(),再插入新的数字及其出现次数。如果没有,直接插入新的数字,其出现次数为1。
时间复杂度是O(N * K * logN)。空间复杂度是O(N)。
C++代码:
#include<iostream>
#include<set>
using namespace std;
struct node {
int num;
int count;
node(int _num, int _count) : num(_num), count(_count) {};
friend bool operator < (node n1, node n2) { //重载小于号才能放进set集合里
if(n1.count == n2.count) {
return n1.num < n2.num;
} else {
return n1.count > n2.count;
}
}
};
int main() {
int N, K;
scanf("%d %d", &N, &K);
int input[N];
for(int i = 0; i < N; i++) {
scanf("%d", &input[i]);
}
set<node> results;
results.insert(node(input[0], 1));
int count[N + 1]; //count[i]统计i出现的次数
fill(count + 1, count + N + 1, 0); //初始化为0次
count[input[0]]++;
for(int i = 1; i < N; i++) {
printf("%d:", input[i]);
int index = 0;
set<node>::iterator it;
for(it = results.begin(); it != results.end(); it++){
printf(" %d", (*it).num); //输出set集合results中的前K项的数字
index++;
if(index >= K){
break;
}
}
it = results.find(node(input[i], count[input[i]])); //在set集合results中寻找数字input[i],其出现次数是count[input[i]]
if(it == results.end()){ //如果没找到
results.insert(node(input[i], 1)); //说明input[i]是一个新的数字,其出现次数为1
}else{
results.erase(it); //如果找到了,先删除set集合中原先的值
results.insert(node(input[i], count[input[i]] + 1)); //往set集合中插入一个新值,其数字是input[i],出现次数是count[input[i]] + 1
}
count[input[i]]++; //增加input[i]出现的次数
printf("\n");
}
return 0;
}
C++解题报告: