AI刷题题解——“34. 游戏排名第三大的分数”| 豆包MarsCode AI 刷题

101 阅读3分钟

该题目的问题描述内容如下:

小M想要通过查看往届游戏比赛的排名来确定自己比赛的目标分数。他希望找到往届比赛中排名第三的分数,作为自己的目标。具体规则如下: 如果分数中有三个或以上不同的分数,返回其中第三大的分数。 如果不同的分数只有两个或更少,那么小M将选择最大的分数作为他的目标。 请你帮小M根据给定的分数数组计算目标分数。

题目所给的输入输出样例为:

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

通过对题目进行简单的分析,不难看出这是一道与数组排序和去重相关的题目,目的是找到数组中第三大的分数,或者在特殊情况下返回最大分数。 要想求解该题,我们应该做到以下几点:

  • 去除重复分数:需要处理重复分数,因为题目要求统计的是不同的分数。
  • 排序操作:需要将分数从大到小排列以确定第三大的分数。
  • 条件判断:根据不同分数的个数决定是返回第三大的分数还是最大分数。

第一眼看到该题时,我的思路大致为:

通过字典来统计每个分数的出现次数,然后根据字典中键的数量来判断是否存在三个或更多的不同分数。如果不同分数不足三个,直接返回最大的分数;否则,将字典的键(即去重后的分数集合)进行降序排序,取排序后的第三个元素作为结果。

具体代码如下:

def solution(n: int, nums: list) -> int: 
    score_hash = {} 
    for score in nums: 
        if score not in score_hash.keys(): 
            score_hash[score] = 0 
        score_hash[score] += 1 
    if len(score_hash.keys()) < 3: 
        return max(score_hash.keys()) 
    s = sorted(score_hash.keys(), reverse=True)  
    return s[2]

但仔细研究后,我们会发现这个思路有可以优化的地方: 我使用了字典 score_hash 来统计每个分数的出现次数,但实际上题目不需要统计频次,只需要去重后的分数集合。字典的额外信息没有被使用,因此可以用更简洁的方法实现。此外,代码的排序操作 sorted 每次都会遍历整个集合并排序,对于大规模输入的有潜在的性能风险。

于是,我们可以选择使用 set 去重,得到不同分数;而对于较大的数据集,我们还可以使用堆的方式维护一个大小为 3 的最小堆来记录前三大的分数,思路和代码如下:

  1. 使用最小堆存储最多 3 个不同的分数。
  2. 遍历数组,遇到新的分数时,根据堆的情况更新。
  3. 如果堆的大小达到 3,堆顶即为第三大的分数;否则返回堆中最大值。
import heapq
def solution(n: int, nums: list) -> int:
    min_heap = []
    unique_scores = set()
    
    for num in nums:
        if num not in unique_scores:
            unique_scores.add(num)
            heapq.heappush(min_heap, num)
            if len(min_heap) > 3:
                heapq.heappop(min_heap)
    
    if len(min_heap) < 3:
        return max(min_heap)
    else:
        return min_heap[0]