具体描述
代码
def solution(nums):
from collections import Counter
# 如果总棋子数不能被 5 整除,直接返回 False
if len(nums) % 5 != 0:
return "False"
# 统计每种棋子的数量
counts = Counter(nums)
# 检查每种棋子的数量是否为 5 的倍数
for count in counts.values():
if count % 5 != 0:
return "False"
return "True"
if __name__ == "__main__":
# 测试用例
print(solution([1, 3, 4, 5, 6, 5, 4]) == "False")
print(solution([1, 1, 1, 1, 2, 1, 2, 2, 2, 2]) == "True")
print(solution([11, 45, 49, 37, 45, 38, 3, 47, 35, 49, 26, 16, 24, 4, 45, 39, 28, 26, 14, 22, 4, 49, 18, 4, 4, 26, 47, 14, 1, 21, 9, 26, 17, 12, 44, 28, 24, 24, 10, 31, 33, 32, 23, 41, 41, 19, 17, 24, 28, 46, 28, 4, 18, 23, 48, 45, 7, 21, 12, 40, 2, 19, 19, 28, 32, 6, 27, 43, 6, 18, 8, 27, 9, 6, 6, 31, 37, 15, 26, 20, 43, 3, 14, 40, 20]) == "
思路
-
问题理解:
- 输入是一组棋子编号(整数序列)。
- 目标是将这些棋子分成若干组,每组恰好5个,并且组内棋子序号必须相同。
- 返回是否可以完成这样的分组。
-
关键点分析:
- 棋子总数:总棋子数量必须是5的倍数,否则直接返回
"False"。 - 每种棋子的数量:统计每种棋子序号的数量,判断每个数量是否是5的倍数。
- 棋子总数:总棋子数量必须是5的倍数,否则直接返回
-
解题步骤:
- 统计总棋子数:首先计算总数,快速判断是否满足总数为5的倍数。
- 统计每种棋子的数量:使用
Counter计算每种棋子的出现次数。 - 逐一检查:验证每种棋子的数量是否是5的倍数。如果有一个不满足,直接返回
"False"。
解法分析
-
使用
collections.Counter来统计棋子数量,这是解决此类分组问题的高效方法。 -
遍历
Counter统计结果,判断每个数量是否是5的倍数,算法简单直观。
分步解析
步骤1:统计棋子总数
if len(nums) % 5 != 0:
return "False"
- 检查总棋子数是否是5的倍数,如果不是,直接返回
"False",节省后续计算。
步骤2:统计每种棋子的数量
counts = Counter(nums)
- 利用
Counter高效统计每种棋子的数量,构造一个字典形式的结果,例如:
nums = [1, 1, 1, 1, 2, 1, 2, 2, 2, 2]
counts = {1: 5, 2: 5}
步骤3:验证分组可行性
for count in counts.values():
if count % 5 != 0:
return "False"
- 遍历统计结果,逐一检查每种棋子的数量是否是5的倍数,如果有一个不是,直接返回
"False"。
步骤4:返回结果
- 如果上述验证全部通过,返回
"True"。
时空复杂度
时间复杂度
- 统计棋子数量:
Counter(nums)需要遍历整个列表,复杂度为 O(N)。 - 验证分组可行性:遍历
Counter的值集合,最多有 N 种不同棋子,复杂度为 O(N)。 - 总复杂度:O(N)。
空间复杂度
- 空间使用:
Counter对象的大小与棋子种类数成正比。如果有 K 种不同棋子,空间复杂度为 O(K)。 - 输入数据:输入数组本身占用 O(N)。
- 总复杂度:O(N+K),通常 K≪N。
总结
这道题的核心在于检查能否将棋子按固定规则分组,即每组包含5个棋子且序号相同。通过数学性质和高效的数据结构,可以快速完成这一任务。首先,利用棋子总数是否为5的倍数进行初步筛选,避免不必要的计算。随后,使用Counter统计各棋子序号的频次,并逐一验证这些频次是否满足5的倍数约束。