青训营笔记 | 游戏排名第三大的分数

264 阅读5分钟

问题描述

小M想要通过查看往届游戏比赛的排名来确定自己比赛的目标分数。他希望找到往届比赛中排名第三的分数,作为自己的目标。具体规则如下:

  1. 如果分数中有三个或以上不同的分数,返回其中第三大的分数。
  2. 如果不同的分数只有两个或更少,那么小M将选择最大的分数作为他的目标。

请你帮小M根据给定的分数数组计算目标分数。

测试样例

样例1:

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

样例2:

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

样例3:

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

solution函数

def solution(n: int, nums: list) -> int:
    unique_nums = sorted(set(nums), reverse=True)
    if len(unique_nums) >= 3:
        return unique_nums[2]
    else:
        return unique_nums[0]

if __name__ == '__main__':
    print(solution(3, [3, 2, 1]) == 1)
    print(solution(2, [1, 2]) == 2)
    print(solution(4, [2, 2, 3, 1]) == 1)

解题思路

整体思路

要根据给定的规则,从分数数组中确定出符合要求的目标分数,核心在于先处理分数数组中重复的分数,得到不同分数的集合,再依据不同分数的数量来决定最终返回的目标分数。

具体步骤

  1. 去重并排序分数

    • 首先,需要将输入的分数数组中的重复分数去除,因为规则是基于不同的分数来判断的。可以利用 Python 中的集合(set)数据结构来轻松实现去重操作,集合的特性就是其中的元素具有唯一性。例如,对于输入的分数数组 nums = [2, 2, 3, 1],通过 set(nums) 操作后,会得到 {1, 2, 3},去除了重复的 2
    • 接着,对去重后的分数集合进行排序,且按照从大到小的顺序排列,以便后续能方便地根据位置获取相应排名的分数。在 Python 中,可以使用内置的 sorted 函数,并设置参数 reverse=True 来实现降序排序。例如,对前面去重后的集合 {1, 2, 3} 进行 sorted(set(nums), reverse=True) 操作后,会得到 [3, 2, 1],分数从大到小排列好了。
  2. 依据不同分数数量确定目标分数

    • 然后,需要统计去重排序后不同分数的个数,也就是判断经过前面步骤得到的列表长度。
    • 如果这个列表的长度大于等于 3,说明存在三个或以上不同的分数,按照规则,此时应该返回列表中索引为 2(Python 中列表索引从 0 开始,索引 2 对应的就是第三大的分数)的元素作为目标分数。例如,对于排序后的列表 [3, 2, 1],就返回 1 作为目标分数。
    • 如果列表长度小于 3(也就是只有两个或更少不同的分数),那么按照规则,要返回最大的分数,也就是列表中的第一个元素(索引为 0 的元素)。例如,对于去重排序后得到 [2, 1] 的情况,就返回 2 作为目标分数。

通过以上的解题思路,就能根据给定的分数数组,按照特定规则准确地计算出小 M 想要的目标分数了。

时间和空间复杂度分析

时间复杂度分析

  1. 去重操作
    使用 Python 中的集合(set)进行去重操作,其时间复杂度通常取决于输入数组中元素的数量 n,平均情况下,将数组转换为集合的时间复杂度是 。这是因为集合内部在处理元素插入等操作时,需要遍历元素来保证唯一性,平均来看每个元素的操作时间是常数级别的,整体是线性时间复杂度。

  2. 排序操作
    对去重后的分数集合进行排序,使用 Python 内置的 sorted 函数(一般基于高效的排序算法,例如 Timsort),其时间复杂度为 ,这里的 k 表示去重后集合中元素的个数(也就是不同分数的个数),因为排序算法需要通过不断比较和交换元素来调整顺序,基于比较的高效排序算法基本都有这样的时间复杂度。由于 k 最大为 n(数组中所有元素都不同的极端情况),且通常 k \leq n,所以这部分的时间复杂度可以表示为  的上界情况(实际会小于等于这个复杂度,取决于不同分数的实际数量)。

  3. 统计数量和返回目标分数操作
    统计去重排序后不同分数的个数以及根据规则返回相应目标分数,这些操作都是对已经处理好的数据进行简单的遍历或者索引访问,时间复杂度为 ,因为它们的执行时间并不随输入数组大小 n 的增加而增加,只涉及常数级别的操作,比如访问列表的某个固定位置元素等。

综合来看,整个算法的时间复杂度主要由去重和排序操作决定,取两者中复杂度较高的,所以总的时间复杂度为 ,其中 n 是输入分数数组中元素的个数。

空间复杂度分析

  1. 去重操作的空间
    使用集合去重时,集合需要额外开辟空间来存储不同的元素,在最坏情况下(所有元素都不同),集合会存储输入数组中的所有 n 个元素,所以去重操作的空间复杂度为 。

  2. 排序操作的空间
    Python 的 sorted 函数在排序过程中,通常会创建临时的辅助空间来辅助排序过程,不过其空间复杂度也是取决于输入元素的数量(也就是去重后不同分数的数量 k),最坏情况是 O(k),同样因为 k \leq n,可以表示为  的上界情况。

除了上述操作外,统计数量和返回目标分数操作基本只涉及几个指针或者变量的使用,占用的空间是常数级别,可以忽略不计。

因此,整个算法总的空间复杂度为 ,其中 n 是输入分数数组中元素的个数,主要由去重和排序操作占用空间的情况决定。