”游戏队友搜索“题解及心得体会 | 豆包MarsCode AI刷题

22 阅读4分钟

题目解析

本题的目的是为一个指定的玩家 id,找到在给定的比赛记录中,符合以下条件的队友:

  1. 队友条件:两名玩家一起参加过至少两局相同的比赛。

  2. 输入

    • ID:指定玩家的 ID。
    • num:比赛历史中总的玩家数量。
    • array:二维数组,每个元素是 (玩家ID, 游戏ID),表示某个玩家参与了一局比赛。
  3. 输出:返回一个列表,包含符合条件的队友的 ID,按照升序排列。如果没有队友,则返回空列表。


解题思路

我们可以分解问题为以下几个步骤:

1. 构建玩家-比赛映射关系

  • 遍历输入的比赛历史记录 ( \text{array} ),为每个玩家建立其参加过的比赛集合。
  • 例如,对于 array = [[1, 1], [1, 2], [2, 1], [3, 2]],得到:
    {
        1: {1, 2},
        2: {1},
        3: {2}
    }
    

2. 确定指定玩家的比赛集合

  • 根据 ( \text{id} ),找到该玩家参加过的比赛集合 games_id。
  • 例如,对于玩家 1,其比赛集合为 {1, 2}

3. 判断队友条件

  • 遍历其他玩家的比赛集合,计算该玩家与 id 的比赛集合交集的大小:
    • 如果交集大小<2,说明该玩家满足队友条件。
  • 将符合条件的玩家 ID 记录下来。

4. 输出结果

  • 将符合条件的队友的玩家 ID 按照升序排列返回。

图解

以示例 1 为例:

输入:

id = 1
array = [
    [1, 1], [1, 2], [1, 3],
    [2, 1], [2, 4], [3, 2],
    [4, 1], [4, 2],
    [5, 2], [5, 3]
]

Step 1: 构建玩家-比赛映射关系:

{
    1: {1, 2, 3},
    2: {1, 4},
    3: {2},
    4: {1, 2},
    5: {2, 3}
}

Step 2: 找到玩家 1 的比赛集合:

games_id = {1, 2, 3}

Step 3: 遍历其他玩家,计算与玩家 1 的比赛集合交集大小:

  • 玩家 2 的比赛集合:{1, 4},交集 {1},大小为 1,不满足条件。
  • 玩家 3 的比赛集合:{2},交集 {2},大小为 1,不满足条件。
  • 玩家 4 的比赛集合:{1, 2},交集 {1, 2},大小为 2,满足条件。
  • 玩家 5 的比赛集合:{2, 3},交集 {2, 3},大小为 2,满足条件。

Step 4: 返回结果:

[4, 5]

Python 实现

以下是完整的代码:

def solution(id, num, array):
    from collections import defaultdict

    # Step 1: 构建玩家-比赛映射
    player_games = defaultdict(set)
    for player_id, game_id in array:
        player_games[player_id].add(game_id)
    
    # Step 2: 找到指定玩家的比赛集合
    target_games = player_games[id]
    if not target_games:
        return []

    # Step 3: 判断队友条件
    teammates = []
    for player_id, games in player_games.items():
        if player_id == id:
            continue  # 跳过自己
        # 计算交集大小
        if len(target_games & games) >= 2:
            teammates.append(player_id)
    
    # Step 4: 返回结果(升序排序)
    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]
    )
    print(
        solution(
            2,
            6,
            [
                [2, 1],
                [2, 3],
                [1, 1],
                [1, 2],
                [3, 1],
                [4, 3],
            ],
        )
        == []
    )
    print(
        solution(
            3,
            8,
            [
                [3, 1],
                [3, 2],
                [3, 3],
                [4, 1],
                [5, 2],
                [6, 3],
                [7, 1],
                [7, 2],
            ],
        )
        == [7]
    )

复杂度分析

  1. 时间复杂度

    • 构建玩家-比赛映射:O(n)O(n),其中 nn 是比赛记录的数量。
    • 遍历玩家计算交集:对于每个玩家,计算交集的时间复杂度为 O(k)O(k),其中 kk 是玩家比赛集合的平均大小。总复杂度为 O(m⋅k)O(m⋅k),其中 mm 是玩家的总数量。
    • 总时间复杂度为 O(n+m⋅k)O(n+m⋅k)。
  2. 空间复杂度

    • 存储玩家-比赛映射,空间复杂度为 O(n)O(n)。

知识点总结

  1. 集合操作:通过 Python 的集合交集操作 &,可以高效计算两个集合的公共元素。
  2. 字典映射:使用 defaultdict 来构建映射关系,可以避免手动初始化字典值。
  3. 排序:在返回结果时,记得对结果列表排序以满足题目要求。

学习建议

  1. 刷题计划
    • 每天选择 3-5 道题目,逐步提升难度,从简单的查找问题到复杂的数据结构问题。
    • 定期复盘错题,总结常见的错误和解题技巧。
  2. 利用 AI 辅助
    • 当遇到不理解的题目时,利用 AI 生成提示和思路,逐步掌握核心算法。
  3. 构建知识体系
    • 分类整理题目:例如,本题可以归类为“集合操作 + 哈希映射”。
    • 针对薄弱环节,例如复杂度优化,多练习相关题目。