问题描述
在一款多人游戏中,每局比赛需要多个玩家参与。如果发现两名玩家至少一起玩过两局比赛,则可以认为这两名玩家互为队友。现在你有一份玩家(通过玩家ID标识)和比赛局次(通过比赛ID标识)的历史记录表,目标是帮助某位指定玩家找到所有符合条件的队友。
例如,已知以下比赛历史记录:
| 玩家ID | 游戏ID |
问题理解
题目要求在一款多人游戏中,根据玩家和比赛的历史记录,找出与指定玩家至少一起玩过两局比赛的所有玩家。这些玩家被认为是指定玩家的队友。题目提供了一个二维数组,其中每个元素是一个包含两个整数的数组,分别表示玩家ID和比赛ID。我们需要根据这些记录,找出与指定玩家互为队友的所有玩家。
数据结构选择
为了高效地解决这个问题,我们需要选择合适的数据结构来存储和处理数据。以下是几种可能的数据结构及其选择逻辑:
-
哈希表(Map):
- 用途:用于存储每个比赛ID对应的玩家列表。
- 选择逻辑:由于我们需要快速查找和更新每个比赛ID对应的玩家列表,哈希表是一个理想的选择。哈希表可以在平均O(1)时间内完成插入和查找操作。
-
集合(Set):
- 用途:用于存储指定玩家参与的所有比赛ID。
- 选择逻辑:集合可以帮助我们快速去重,并且可以在O(1)时间内检查某个比赛ID是否存在。
-
计数器(Counter):
- 用途:用于统计每个玩家与指定玩家一起比赛的次数。
- 选择逻辑:通过计数器,我们可以快速统计每个玩家与指定玩家一起比赛的次数,从而判断他们是否互为队友。
算法步骤
-
初始化数据结构:
- 创建一个哈希表
mp,用于存储每个比赛ID对应的玩家列表。 - 创建一个集合
np,用于存储指定玩家参与的所有比赛ID。
- 创建一个哈希表
-
遍历输入数组:
- 对于每个记录
[playerID, gameID],如果playerID是指定玩家,则将gameID添加到集合np中。 - 将
playerID添加到哈希表mp中对应的gameID列表中。
- 对于每个记录
-
统计队友:
- 创建一个计数器
cnt,用于统计每个玩家与指定玩家一起比赛的次数。 - 遍历集合
np中的每个比赛ID,对于每个比赛ID,遍历哈希表mp中对应的玩家列表,增加这些玩家在计数器cnt中的计数。
- 创建一个计数器
-
筛选队友:
- 遍历计数器
cnt,找出所有与指定玩家一起比赛次数大于等于2的玩家,并将他们添加到结果列表中。
- 遍历计数器
时间复杂度分析
- 初始化数据结构:O(1)
- 遍历输入数组:O(n),其中n是输入数组的长度。
- 统计队友:O(m * k),其中m是集合
np的大小,k是每个比赛ID对应的玩家列表的平均长度。 - 筛选队友:O(p),其中p是计数器
cnt的大小。
总体时间复杂度为O(n + m * k + p),在大多数情况下,m和k都相对较小,因此算法是高效的。
空间复杂度分析
- 哈希表
mp:O(n) - 集合
np:O(m) - 计数器
cnt:O(p)
总体空间复杂度为O(n + m + p),在大多数情况下,n、m和p都相对较小,因此空间复杂度是可以接受的。
cpp代码如下:
std::vector<int> solution(int id, int num, std::vector<std::vector<int>> array) {
// 用于存储指定玩家参与的所有比赛ID
set<int> np;
// 用于存储每个比赛ID对应的玩家列表
map<int, vector<int>> mp;
// 遍历输入数组,填充 np 和 mp
for(auto item : array) {
int nid = item[0], pid = item[1];
if(nid == id) {
// 如果当前玩家ID是指定玩家,则将比赛ID添加到 np 中
np.insert(pid);
}
// 将当前玩家ID添加到对应比赛ID的玩家列表中
mp[pid].push_back(nid);
}
// 用于统计每个玩家与指定玩家一起比赛的次数
map<int, int> cnt;
// 遍历指定玩家参与的所有比赛ID
for(auto x : np) {
// 遍历每个比赛ID对应的玩家列表
for(auto item : mp[x]) {
// 统计每个玩家与指定玩家一起比赛的次数
cnt[item]++;
}
}
// 用于存储最终结果
vector<int> ans;
// 遍历计数器,找出所有与指定玩家一起比赛次数大于等于2的玩家
for(auto [k, v] : cnt) {
if(k != id && v >= 2) {
// 如果玩家不是指定玩家且一起比赛次数大于等于2,则将其添加到结果列表中
ans.push_back(k);
}
}
// 返回结果列表
return ans;
}
总结
通过选择合适的数据结构和算法步骤,我们可以高效地解决这个问题。哈希表和集合的使用使得我们能够快速查找和更新数据,而计数器则帮助我们统计每个玩家与指定玩家一起比赛的次数。最终,我们可以通过遍历计数器来筛选出所有符合条件的队友。