在这道题中,我们需要找到所有与某位指定玩家(通过其 ID 标识)至少一起玩过两局比赛的玩家。
这是一个基于关系图的简单问题,核心在于:
- 解析比赛记录,构建玩家与比赛的参与关系。
- 统计每个玩家与指定玩家的共同比赛次数。
- 筛选出共同比赛次数大于等于 2 的玩家并输出。
解题思路
1. 比赛记录的结构化分析
比赛记录 array 由一组 [player_id, match_id] 组成,表示玩家 player_id 参加了比赛 match_id。
对于指定玩家,我们需要从记录中找到:
- 他参加过的所有比赛的
match_id。 - 其他玩家是否在这些比赛中也出现过,并统计每个玩家的共同比赛次数。
2. 分析拆解
- 步骤 1:解析记录,提取指定玩家
id参与的所有比赛matches。 - 步骤 2:遍历比赛记录,找出与
id的比赛有交集的玩家,记录这些玩家的共同比赛次数。 - 步骤 3:筛选共同比赛次数大于等于 2 的玩家,将结果排序返回。
3. 数据结构选择
- 使用字典
teammate_counts,键为玩家 ID,值为与指定玩家的共同比赛次数。 - 使用集合
matches存储指定玩家参加的比赛match_id,以便快速查找。
4. 优化点
- 通过集合和字典快速查找比赛关联性,减少重复计算。
- 筛选条件和排序操作简洁清晰。
实现代码
下面是基于上述分析的代码实现:
def solution(id, num, array):
from collections import defaultdict
# 找到指定玩家参与的所有比赛
matches = set(match_id for player_id, match_id in array if player_id == id)
# 记录与指定玩家的共同比赛次数
teammate_counts = defaultdict(int)
# 遍历所有比赛记录
for player_id, match_id in array:
# 如果当前比赛属于指定玩家参与的比赛,记录其他玩家出现的次数
if match_id in matches and player_id != id:
teammate_counts[player_id] += 1
# 筛选出共同比赛次数至少为2的玩家,并排序
teammates = [player for player, count in teammate_counts.items() if count >= 2]
return sorted(teammates)
if __name__ == "__main__":
# 测试用例
print(
solution(
1,
10,
[
[1, 1],
[1, 2],
[1, 3],
[2, 1],
[2, 4],
[3, 2],
[4, 1],
[4, 2],
[5, 2],
[5, 3],
],
)
== [4, 5]
)
测试用例解析
测试用例 1
输入:
id = 1,
array = [[1, 1], [1, 2], [1, 3], [2, 1], [2, 4], [3, 2], [4, 1], [4, 2], [5, 2], [5, 3]]
-
解析记录:指定玩家
1参与了比赛{1, 2, 3}。 -
统计次数:
- 玩家
2:比赛{1}(1次)。 - 玩家
3:比赛{2}(1次)。 - 玩家
4:比赛{1, 2}(2次)。 - 玩家
5:比赛{2, 3}(2次)。
- 玩家
-
筛选结果:
[4, 5]。
测试用例 2
输入:
id = 3,
array = [[1, 1], [1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2], [3, 3], [4, 2], [4, 3]]
-
解析记录:指定玩家
3参与了比赛{1, 2, 3}。 -
统计次数:
- 玩家
1:比赛{1, 2, 3}(3次)。 - 玩家
2:比赛{1, 3}(2次)。 - 玩家
4:比赛{2, 3}(2次)。
- 玩家
-
筛选结果:
[1, 2, 4]。
时间复杂度分析
- 提取指定玩家比赛:
遍历array一次,时间复杂度为 O(N)。 - 统计其他玩家的比赛次数:
遍历array一次,检查match_id是否在matches中(集合查找 O(1)),总复杂度为 O(N)。 - 筛选结果并排序:
筛选和排序的时间复杂度为 O(MlogM),其中 MMM 是符合条件的玩家数。
总时间复杂度为 O(N+MlogM)。