2025B-垃圾短信识别-200分
刷题笔记合集🔗
问题描述
随着移动通信的普及,垃圾短信也越来越多,给人们的生活带来了很多烦恼。为了识别垃圾短信发送者,我们需要分析短信发送和接收的模式。
在这个问题中,我们将使用以下规则来识别垃圾短信发送者:
- 如果一个用户A发送短信给超过5个没有回复过A的用户,则A可能是垃圾短信发送者。
- 如果一个用户A发送的短信总数比收到的短信总数多10条以上,则A可能是垃圾短信发送者。
- 如果存在用户X,用户A发送给X的短信比X发送给A的短信多5条以上,则A可能是垃圾短信发送者。
如果满足以上任一条件,则认为该用户是垃圾短信发送者。
输入格式
第一行包含一个整数 ,表示短信记录的数量。
接下来的 行,每行包含两个整数
和
,分别表示发送者ID和接收者ID。
最后一行包含一个整数 ,表示要检查的用户ID。
输出格式
输出一行,包含三个值,用空格分隔:
- 第一个值是 "true" 或 "false",表示用户
是否是垃圾短信发送者。
- 第二个值是一个整数
,表示用户
发送短信给的没有回复过
的用户数量。
- 第三个值是一个整数
,表示用户
发送的短信总数减去收到的短信总数。
样例输入1
12
1 2
1 3
1 4
1 5
1 6
1 7
1 8
2 1
3 10
4 10
5 10
6 10
1
样例输出1
true 6 7
样例输入2
15
2 1
2 1
2 1
2 1
2 1
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1
样例输出2
false 0 5
样例输入3
10
1 2
1 2
1 2
1 2
1 2
1 2
1 2
2 1
3 4
5 6
1
样例输出3
true 0 6
样例1 | 用户1发送短信给用户2、3、4、5、6、7、8,但只有用户2回复了用户1,所以l=6。用户1发送了7条短信,收到了1条短信,所以m=6。由于l>5,所以用户1是垃圾短信发送者。 |
样例2 | 用户1发送短信给用户2,用户2也回复了用户1,所以l=0。用户1发送了10条短信,收到了5条短信,所以m=5。由于l≤5且m≤10,且不存在用户X使得用户1发送给X的短信比X发送给用户1的短信多5条以上,所以用户1不是垃圾短信发送者。 |
样例3 | 用户1发送7条短信给用户2,但只收到用户2的1条短信,所以用户1发送给用户2的短信比用户2发送给用户1的短信多6条,满足条件3,因此用户1是垃圾短信发送者。 |
数据范围
题解
这道题目要求我们识别垃圾短信发送者,需要根据三个条件来判断:
- 发送短信给超过5个没有回复过的用户
- 发送的短信总数比收到的短信总数多10条以上
- 存在用户X,发送给X的短信比X发送给自己的短信多5条以上
解题思路:
- 统计用户发送和接收的短信记录
- 计算没有回复过的用户数量l
- 计算发送短信总数与接收短信总数的差值m
- 检查是否存在满足条件3的用户X
- 根据三个条件判断是否是垃圾短信发送者
时间复杂度分析:
- 统计短信记录需要
的时间
- 计算l和m需要
的时间,其中k是与用户tid有交互的用户数量
- 检查条件3需要
的时间
- 因此,总的时间复杂度是
空间复杂度分析:
- 存储短信记录需要
的空间
- 因此,总的空间复杂度是
对于给定的数据范围,这个算法是高效的,可以在合理的时间内得到结果。
参考代码
# 输入获取
n = int(input())
msg_list = [input().split() for i in range(n)]
user_id = input()
# 算法入口
def check_spam(uid, msgs):
# 记录发送和接收的消息
out_msgs = []
in_msgs = []
# 记录发送和接收的次数
out_cnt = {}
in_cnt = {}
# 处理所有消息记录
for s_id, r_id in msgs:
# 处理发送的消息
if s_id == uid:
out_msgs.append(r_id)
if r_id in out_cnt:
out_cnt[r_id] += 1
else:
out_cnt[r_id] = 1
# 处理接收的消息
if r_id == uid:
in_msgs.append(s_id)
if s_id in in_cnt:
in_cnt[s_id] += 1
else:
in_cnt[s_id] = 1
# 计算发送和接收的用户集合
out_set = set(out_msgs)
in_set = set(in_msgs)
# 计算有交互的用户
chat_list = [x for x in out_set if x in in_set]
# 计算关键指标
no_reply = len(out_set) - len(chat_list)
msg_diff = len(out_msgs) - len(in_msgs)
# 判断是否为垃圾短信发送者
is_spam = no_reply > 5 or msg_diff > 10
# 如果前两个条件不满足,检查第三个条件
if not is_spam:
for uid2 in out_set:
sent = out_cnt[uid2]
recv = in_cnt.get(uid2, 0)
if sent - recv > 5:
is_spam = True
break
# 返回结果
return f"{str(is_spam).lower()} {no_reply} {msg_diff}"
# 算法调用
print(check_spam(user_id, msg_list))
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <string>
using namespace std;
/**
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
算法刷题笔记 文章被收录于专栏
本专栏收集并整理了一些刷题笔记