PAT-ADVANCED1129——Recommendation System

本文详细解析PAT-ADVANCED 1129推荐系统题目,介绍了一个基于用户访问项目频率的简易推荐算法实现,通过使用C++的set集合和结构体,实现了对用户偏好的评级和推荐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我的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++解题报告:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值