红包运气排行榜 | 豆包MarsCode AI刷题

214 阅读5分钟

1. 问题概述

在一个多人参与的抢红包游戏中,每个人会抢到一定的红包金额。目标是对所有参与者根据其抢到的金额进行排序,金额越多的排前面;如果金额相同,则按照参与抢红包的顺序(即谁先抢谁排前)进行排名。

具体来说,给定一个参与者的列表和每个人抢到的金额,要求输出按金额降序排列的参与者列表。如果两个人金额相同,则按他们抢红包的顺序进行排序。

2. 输入与输出

输入
  • n: 一个整数,表示参与抢红包的总人数(1 ≤ n ≤ 1000)。
  • s: 一个长度为n的字符串列表,表示每个参与者的名字。
  • x: 一个长度为n的整数列表,表示每个参与者抢到的红包金额。
输出
  • 返回一个字符串列表,表示按照要求排序后的参与者名字列表。
例子

样例1

输入:

n = 4 
s = ["a", "b", "c", "d"] 
x = [1, 2, 2, 1]

输出:

['b', 'c', 'a', 'd']

样例2

输入:

n = 3 
s = ["x", "y", "z"] 
x = [100, 200, 200]

输出:

['y', 'z', 'x']

样例3

输入:

n = 5 
s = ["m", "n", "o", "p", "q"] 
x = [50, 50, 30, 30, 20]

输出:

['m', 'n', 'o', 'p', 'q']

3. 思路分析

这个问题的核心是排序。我们需要对每个参与者的红包金额进行排序,并且在金额相同的情况下,按照他们抢红包的顺序排序。

为了实现这个功能,我们可以利用Python的排序功能。Python的排序支持自定义排序规则,并且它稳定排序(即如果两个元素相等,它们的相对位置不会改变),这对于我们的需求非常适用。

4. 解决方案

为了进行排序,我们需要记录每个参与者的:

  1. 总抢红包金额。
  2. 第一次抢红包的顺序(在金额相同的情况下使用)。

在实现时,我们可以利用一个字典来存储每个参与者的抢红包金额和他们第一次参与的索引(顺序)。然后我们将这些信息组成一个元组列表,使用自定义的排序规则进行排序。

具体步骤如下:

  1. 初始化数据结构

    • 使用字典total_amount来记录每个人的总金额。
    • 使用字典first_index来记录每个人第一次出现的顺序。
  2. 更新字典

    • 遍历每个参与者,更新他们的总金额。
    • 记录第一次抢红包的顺序。
  3. 排序

    • 我们将每个参与者的名字、总金额和第一次抢红包的顺序组织成元组。
    • 按照金额降序和顺序升序对元组列表进行排序。
  4. 输出结果

    • 排序后,我们只需要提取排序后的名字并返回即可。

5. 代码实现

def solution(n: int, s: list, x: list) -> list:
    # 使用字典记录每个人的总抢红包金额和第一次抢红包的顺序
    total_amount = {}
    first_index = {}
    
    for i in range(n):
        name = s[i]
        amount = x[i]
        
        # 更新总金额
        if name in total_amount:
            total_amount[name] += amount
        else:
            total_amount[name] = amount
            first_index[name] = i  # 记录第一次抢红包的顺序
    
    # 将字典转换为元组列表
    people = [(name, total_amount[name], first_index[name]) for name in total_amount]
    
    # 对这个元组列表进行排序,排序规则是先按金额降序排序,如果金额相同,则按第一次抢红包的顺序升序排序
    people.sort(key=lambda p: (-p[1], p[2]))
    
    # 提取排序后的名字列表作为结果
    return [p[0] for p in people]

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'])

6. 代码解析

  • 数据结构

    • total_amount: 记录每个玩家的总金额。
    • first_index: 记录每个玩家的首次参与顺序。
  • 排序

    • 我们使用了Python内建的sort()函数,并传入了一个lambda函数作为排序的关键字(key)。这个lambda函数指定了排序的规则:

      • -p[1]: 按照总金额降序排列。
      • p[2]: 如果金额相同,则按照第一次抢红包的顺序升序排列。
  • 时间复杂度

    • 构建字典需要O(n)的时间。
    • 排序操作的时间复杂度为O(n log n),其中n是参与者的数量。
    • 因此,整体时间复杂度为O(n log n),适用于n最大为1000的情况。

7. 测试用例

  • 测试用例1: 输入:["a", "b", "c", "d"], [1, 2, 2, 1],输出:['b', 'c', 'a', 'd']
  • 测试用例2: 输入:["x", "y", "z"], [100, 200, 200],输出:['y', 'z', 'x']
  • 测试用例3: 输入:["m", "n", "o", "p", "q"], [50, 50, 30, 30, 20],输出:['m', 'n', 'o', 'p', 'q']

8. 总结

这个问题的关键在于理解如何通过字典存储每个参与者的红包金额和首次参与的顺序,然后利用排序对这些参与者进行合理的排名。在实际应用中,Python提供的排序函数和稳定排序特性大大简化了代码的实现,使得我们能够高效地解决这个问题。