青训营X豆包MarsCode 技术训练营:分组飞行棋棋子Python题解 | 豆包MarsCode AI 刷题

130 阅读5分钟

问题描述

小M和小F在玩飞行棋。游戏结束后,他们需要 将桌上的飞行棋棋子分组整理好。现在有N个 棋子,每个棋子上有一个数字序号。小M的目 标是将这些棋子分成M组,每组恰好5个,并且 组内棋子的序号相同。小M希望知道是否可以 按照这种方式对棋子进行分组。 例如,假设棋子序号为[1,2,3,4,5],虽 然只有5个棋子,但由于序号不同,因此不能形 成有效的分组。如果序号是[1,1,1,1,1 2,2,2,2,2],则可以形成两个有效分组: 因此输出为 True.

测试样例

样例1:

输入:nums =[1,2,3,4,5]

输出:"False'

样例2:

输入:nums =[1,1,1,1,2,1,2, 2,2,2]

输出:"True”

样例3:

输入:nums=[5,5,5,5,5,5,5, 5,5,5]

输出:"True"

解题思路

题目要求判断一个数组中是否每个元素的出现次数都是5的倍数。我们可以借助Python的 Counter 类来统计每个元素的出现次数,然后检查每个元素的计数是否都能被5整除。

代码

from typing import Counter


def solution(nums):
    count = Counter(nums)
    for key in count:
        if count[key] % 5 != 0:
            return "False"
    return "True"

if __name__ == "__main__":
    #  You can add more test cases here
    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]
) == "False")

关键代码解释

Counter 会返回一个字典,其中键是数组中的唯一元素,值是该元素在数组中的出现次数。例如,Counter([1, 1, 1, 2, 2, 2]) 会返回 {1: 3, 2: 3}

for循环里,遍历每个元素的计数,如果发现某个计数不是5的倍数,则立即返回 "False"。如果遍历结束都符合条件,则返回 "True"

时间和空间复杂度分析

  • 时间复杂度O(n),其中 n 是数组的长度。统计每个元素的频次需要 O(n) 时间,然后遍历所有唯一元素的频次需要 O(m),其中 m 是数组中唯一元素的数量。总体时间复杂度为 O(n + m),最坏情况下接近 O(n)
  • 空间复杂度O(m),其中 m 是数组中唯一元素的数量。Counter 类会存储每个唯一元素及其出现次数,因此空间复杂度取决于唯一元素的数量。

学习思路

在 Python 中,Countercollections 模块中的一个类,用于快速计数和管理元素的出现频次。它可以统计可迭代对象(如字符串、列表、元组等)中每个元素的出现次数,并返回一个类似字典的对象,键是元素,值是它的出现次数。 此题运用Counter是很好的一个选择,它自动就帮我们把每个元素出现的次数统计好了,我们只需要遍历它返回的字典即可,但是这个用法是Python里的,其他语言不支持这种方法。

1. 引入和基础使用

首先需要从 collections 模块引入 Counter

from collections import Counter

基本使用示例

假设我们想统计字符串 'aabbbcc' 中每个字符的出现次数,可以这样使用 Counter

counter = Counter('aabbbcc')
print(counter)
# 输出: Counter({'b': 3, 'a': 2, 'c': 2})

在这个例子中,Counter 返回一个类似字典的对象,其中键是字符,值是每个字符的出现次数。

2. 常用方法和操作

初始化

Counter 可以接收不同的输入类型进行初始化:

  • 字符串:按字符统计
  • 列表或元组:按元素统计
  • 字典:直接将字典的键值对视为元素及其频次
# 使用字符串初始化
counter1 = Counter('hello')
print(counter1)  # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})

# 使用列表初始化
counter2 = Counter([1, 2, 2, 3, 1, 3, 3])
print(counter2)  # Counter({3: 3, 1: 2, 2: 2})

# 使用字典初始化
counter3 = Counter({'a': 2, 'b': 3})
print(counter3)  # Counter({'b': 3, 'a': 2})
访问元素频次

类似字典,访问某个元素的频次可以通过键进行查询:

print(counter1['l'])  # 输出: 2

若查询一个未出现的元素,返回 0 而不是报错:

print(counter1['x'])  # 输出: 0
更新计数

使用 update 方法增加已有计数或加入新元素:

counter1.update('hello')
print(counter1)  # Counter({'l': 4, 'h': 2, 'e': 2, 'o': 2})
减少计数

可以用 subtract 方法减少指定元素的计数:

counter1.subtract('he')
print(counter1)  # Counter({'l': 4, 'o': 2, 'h': 1, 'e': 1})
查找最常见的元素

Counter.most_common() 返回一个按频次降序排列的元素列表,方便找到最常见的元素:

print(counter1.most_common(2))  # [('l', 4), ('o', 2)]
删除或清空计数

使用 del 可以删除某个元素,clear 则可以清空所有计数:

del counter1['h']
print(counter1)  # Counter({'l': 4, 'o': 2, 'e': 1})

counter1.clear()
print(counter1)  # Counter()

总结

Counter 是一个方便的计数工具,适合处理简单的计数统计需求。