红包运气排行榜题目解析

2 阅读3分钟

思路:

题目要求对参与抢红包的人进行运气排名。排名规则如下:

  1. 抢到的金额越多,排名越靠前。
  2. 如果两个人抢到的金额相同,则按照他们抢红包的顺序进行排名。

数据结构选择

  1. 字典(Dictionary) :用于存储每个用户的抢红包信息。字典的键是用户名,值是一个包含两个元素的列表,第一个元素是抢到的总金额,第二个元素是该用户第一次抢红包的索引(即顺序)。
  2. 列表(List) :用于存储最终的排名结果。

算法步骤

  1. 初始化字典:使用 defaultdict 来初始化字典,确保每个用户名对应的值是一个包含两个元素的列表,初始值为 [0, -1]
  2. 遍历输入数据:遍历每个用户的抢红包记录,更新字典中的金额和索引。
  3. 打包数据:将字典中的数据打包成一个列表,每个元素是一个包含用户名、总金额和索引的三元组。
  4. 排序:按照金额降序排序,金额相同的情况下按照索引升序排序。
  5. 提取结果:从排序后的列表中提取用户名,形成最终的排名结果。 代码如下:
from collections import defaultdict
def solution(n: int, s: list, x: list) -> list:
    dic=defaultdict(lambda:[0,float('inf')])
    for i in range(n):
        name=s[i]
        amount=x[i]
        dic[name][0]+=amount
        dic[name][1]=min(dic[name][1],i)#记录最早的索引
        # dic[name][1]=i

    # 将红包信息和索引一起打包
    res = [(a,b[0],b[1]) for a,b in dic.items()]
    
    # 按照金额降序排序,金额相同的情况下按照索引升序排序
    res.sort(key=lambda x: (-x[1], x[2]))
    
    # 打印排序后的结果
    print(res)
    
    # 提取排序后的名字
    ans = [a for a, b, c in res]
    
    return ans

if __name__ == '__main__':
    print(solution(4, ["a", "b", "c", "d"], [1, 2, 2, 1]) == ['b', 'c', 'a', 'd'])
    print(solution(3, ["x", "y", "z"], [100, 200, 200]) == ['y', 'z', 'x'])
    print(solution(5, ["m", "n", "o", "p", "q"], [50, 50, 30, 30, 20]) == ['m', 'n', 'o', 'p', 'q'])
    print(solution(12, ["aa","aaaaaaa","aaaa","aaaa","aaaa","aaaaaaaaaa","aaaaaaaaa","aaaa","aaaaaaaaaa","aaaaaaaaa","aaaaa","aaaa"], [17,14,11,2,8,16,14,17,10,6,5,12]))

注意到这里用到了python collections中的defaultdict,关于defaultdict的用法如下: efaultdict 是 Python 标准库 collections 模块中的一个类,它继承自内置的 dict 类,并提供了一个额外的功能:当访问一个不存在的键时,它会自动创建该键,并使用指定的默认值进行初始化。

defaultdict 的主要用途是避免在处理字典时频繁检查键是否存在。你可以通过传递一个可调用对象(如函数、lambda 表达式等)来指定默认值的生成方式。

为什么使用 defaultdict

  1. 避免键不存在时的错误

    使用普通的 dict,当你访问一个不存在的键时,会抛出 KeyError 异常。而 defaultdict 会自动创建该键并初始化.

  2. 简化代码

    • 使用 defaultdict 可以减少代码中的条件检查,使代码更加简洁和易读。

题目疑惑点解析: 代码中为什么是dic[name][1]=min(dic[name][1],i) 而不是dic[name][1]=i? 这个的话是要考虑到要存储的是抢红包最早的人的序号,如果是dic[name][1]=i,那么会随着i的变化,红包的人的序号也会变化,因此不行