题目解析-分组飞行棋棋子(python)

60 阅读4分钟

题面

小M和小F在玩飞行棋。游戏结束后,他们需要将桌上的飞行棋棋子分组整理好。现在有 N 个棋子,每个棋子上有一个数字序号。小M的目标是将这些棋子分成 M 组,每组恰好5个,并且组内棋子的序号相同。小M希望知道是否可以按照这种方式对棋子进行分组。

例如,假设棋子序号为 [1, 2, 3, 4, 5],虽然只有5个棋子,但由于序号不同,因此不能形成有效的分组。如果序号是 [1, 1, 1, 1, 1, 2, 2, 2, 2, 2],则可以形成两个有效分组,因此输出为 True

问题分析

小M希望将 N 个棋子分成 M 组,每组恰好 5 个棋子,并且每组中的棋子的序号相同。我们的任务是判断是否能按照这种方式进行分组。

要做到这一点,我们需要:

  1. 每组有 5 个相同序号的棋子:这意味着棋子序号的出现频次必须是 5 的倍数。
  2. 总共有 M 组:可以通过统计每个棋子的频次来判断能否形成 M 组。

解题思路

  1. 统计棋子序号的频次:我们首先统计所有棋子序号的出现次数。
  2. 检查每个频次是否为 5 的倍数:每个序号的棋子数量必须是 5 的倍数。如果有任何一个序号的频次不能被 5 整除,则返回 False
  3. 计算分组数量:通过将每个序号的频次除以 5,我们得到每个序号可以组成的组数。如果所有序号的组数之和等于 M,则返回 True,否则返回 False

解题步骤

  1. 使用 Counter 来统计每个棋子序号的频次。
  2. 遍历每个棋子序号,检查其频次是否为 5 的倍数,并计算能组成的组数。
  3. 如果总组数等于 M,则输出 True,否则输出 False

代码实现

from collections import Counter

def canDivideIntoGroups(chess_pieces, M):
    # 统计每个棋子序号的频次
    freq = Counter(chess_pieces)
    
    # 计算总共能组成的组数
    total_groups = 0
    
    # 遍历每个棋子的序号和频次
    for count in freq.values():
        # 如果某个频次不能被 5 整除,则无法分组
        if count % 5 != 0:
            return False
        # 计算当前序号可以组成的组数
        total_groups += count // 5
    
    # 检查是否能组成 M 组
    return total_groups == M

# 测试案例
chess_pieces1 = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
M1 = 2
print(canDivideIntoGroups(chess_pieces1, M1))  # 输出: True

chess_pieces2 = [1, 2, 3, 4, 5]
M2 = 1
print(canDivideIntoGroups(chess_pieces2, M2))  # 输出: False

代码解释

  1. Counter(chess_pieces) :通过 Counterchess_pieces 中的每个棋子序号进行计数,得到一个字典,键是棋子序号,值是该序号出现的次数。

  2. 遍历频次:通过 for count in freq.values() 遍历每个棋子序号的出现频次,检查是否能够分组。

    • 如果某个序号的频次不能被 5 整除,直接返回 False
    • 如果能被 5 整除,则将频次除以 5,得到该序号可以组成的组数。
  3. 总组数检查:将所有序号组成的组数加起来,判断是否等于 M。如果相等,则返回 True,否则返回 False

复杂度分析

  • 时间复杂度:O(N),其中 N 是棋子的数量。我们需要对棋子序号进行一次遍历,统计其频次,然后再遍历频次进行判断。
  • 空间复杂度:O(K),其中 K 是不同棋子序号的数量。我们使用 Counter 存储每个序号的频次,空间复杂度与不同序号的数量成正比。

测试案例

  1. 测试用例 1

    chess_pieces = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
    M = 2
    print(canDivideIntoGroups(chess_pieces, M))  # 输出: True
    
    • 解释:可以将序号 1 和 2 的棋子分别分成两组,每组 5 个。
  2. 测试用例 2

    chess_pieces = [1, 2, 3, 4, 5]
    M = 1
    print(canDivideIntoGroups(chess_pieces, M))  # 输出: False
    
    • 解释:虽然有 5 个棋子,但它们的序号不同,无法组成一组。
  3. 测试用例 3

    chess_pieces = [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2]
    M = 2
    print(canDivideIntoGroups(chess_pieces, M))  # 输出: False
    
    • 解释:序号 1 有 7 个棋子,无法组成一个完整的组,因此无法组成有效的分组。

总结

通过统计棋子的频次并验证每个频次是否是 5 的倍数,我们可以高效地判断是否可以将棋子分成指定数量的组。