PAT甲组1129 Recommendation System 思路解析和代码

A1129

题目链接

个人思路

题意:对英文阅读理解有一定要求,我就是卡在Access这个词上(应译为访问),结果一直不明白这道题的含义
给出用户点击item的次序,要系统根据用户对item的点击次数(最大的优先推荐,次数相等推荐编号最小的),在用户下一次点击item前,给出推荐item编号,推荐个数最多不超过K个
PS:第一个item没有推荐,因为之前没有访问记录
关键要完成边插入边排序,在序列打乱的情况下快速访问插入

个人思考过程

  • 结构体,能很好的排序但发现无法快速访问,如何能在排序后快速访问(暴力求解,至少能得一半的分数)
  • map,能快速访问,但无法按题目要求排序
  • multimap,按键排序,值只是按先后顺序

思路
然后看了几个大佬的博客,才知道此题是使用STL容器存储结构体,并重载运算符(没错,这样可以随心所欲的排序)进行增删改查。读入数据时,查询集合中数据是否存在,若存在则先删除再插入,不存在直接插入即可

自己在实现过程中还是遇到了一些问题:

  • 一开始重载运算符使用的是声明友元函数(依照优先队列重载运算符的方法),此时会报错
  • STL(结构体)查找时是会比较结构体中的所有成员,所有数据一致为查找成功。要注意 点击次数自增代码的位置(cntAccess[data]++;),应该在查找后再自增,如果在查找前就已经自增了,则永远不会比对成功

暴力代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50005;
int N, K;
struct Rec{
	int data;
	int cnt;
}rec[maxn];
bool cmp(Rec r1, Rec r2)
{
	if(r1.cnt != r2.cnt)
		return r1.cnt > r2.cnt;
	else
		return r1.data < r2.data;
}
int cntAccess[maxn];
multimap<int, int> cnt2id;
int main(int argc, char *argv[]) {
	scanf("%d%d", &N, &K);
	int size = 0;
	for(int i = 0; i < N; ++i)
	{
		int data;
		scanf("%d", &data);
		rec[i].data = data;
		if(i != 0)
		{
			sort(rec, rec + i + 1, cmp);
			printf("%d: ", data);
			for(int j = 0; j < min(K, size); ++j)
			{
				printf("%d", rec[j].data);
				if(j < min(K, size) - 1)
					printf(" ");
				else
					printf("\n");
			}
			size++;
		}
		for(int j = 0; j <= i; ++j)
		{
			if(rec[j].data == data)
			{
				rec[j].cnt++;
				break;
			}
		}
		if(i == 0)
		{
			size++;
			continue;
		}	
	}
	return 0;
}

在这里插入图片描述

AC代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50005;
int N, K;
struct Rec{
	int data;
	int cnt;
	bool operator < (const Rec &r1)const
	{
		if(r1.cnt != cnt)
			return cnt > r1.cnt;//cnt大的排在前面 
		else
			return data < r1.data;//data小的排在前面 
	}
	/*friend bool operator < (Rec r1, Rec r2)//会出错
	{
		if(r1.cnt != r2.cnt)
			return r1.cnt < r2.cnt;//cnt大的排在前面 
		else
			return r1.data > r1.data;//data小的排在前面 
	}*/
	Rec(){}
	Rec(int dd, int cc)
	{
		data = dd;
		cnt = cc;
	}
};
set<Rec> st; 
int cntAccess[maxn];
int main(int argc, char *argv[]) {
	scanf("%d%d", &N, &K);
	int data;
	scanf("%d", &data);
	cntAccess[data]++;
	st.insert(Rec(data, cntAccess[data]));
	for(int i = 1; i < N; ++i)
	{
		scanf("%d", &data);
		printf("%d:", data);
		int num = 0;
		for(set<Rec>::iterator j = st.begin(); j != st.end(); ++j)
		{
			if(num < K)
				printf(" %d", j->data);
			else
				break;
			num++;
		}
		printf("\n");
		set<Rec>::iterator it = st.find(Rec(data, cntAccess[data]));//先查询,此时cntAccess不做自增操作
		if(it != st.end())//集合中存在当前数据 
			st.erase(it);//删除重新插入更新
		cntAccess[data]++;//查询后再做自增操作
		st.insert(Rec(data, cntAccess[data]));//直接插入 	
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值