青训7_1114_01 红包运气排行榜(系统示例有问题,故此题不计入刷题数_附正确答案)_知识含量较密集

青训7_1114_01 红包运气排行榜(系统示例有问题,故此题不计入刷题数_附正确答案)

一、问题描述

小C参与了一场抢红包的游戏,现在他想要对所有参与抢红包的人进行一次运气排名。排名规则如下:抢到的金额越多,排名越靠前;如果两个人抢到的金额相同,则按照他们抢红包的顺序进行排名。比如,如果小C和小U抢到的金额相同,但小C比小 先抢,则小C排在小U前面。

1.2测试样例

样例1
输入:n= 4,S=["a",“b","c",“d"],X = [1,2,2,1]输出:["b’,'c,'a','d']
样例2:
输入:n= 3,S=["x",“y",“2" ,X=[100,200,200]输出:['y’,'z','x"]
样例3:
输入:n = 5 , 5 = ["m", "n", "0", "р"', "q"],X = [50,50,30,30,20]输出:['m','n','o, 'p', 'q']

1.3示例

def solution(n: int, s: list, x: list) -> list:
    # write code here
    pass

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

二、基础思路

找一个有序数组进行排列,按照字典的key进行排序。

此处有问题在于,只选择同一个人的最大红包数后,重新进行排序。

2.2 解题思路:

同一个人多次抢红包只算最大值

不同人金额不同时按金额排序

不同人金额相同时按首次抢红包顺序排序

保持排序的稳定性

## 2.3 系统例子有问题(系统预期输入并不正确,导致无法通过程序)

s中明显最大是aa即17,因此aa和aaaa都是17,也应该aa先排前。而答案直接是错误的。从aa不是被排在第一个就有问题。

在这里插入图片描述

三、答案

def solution(n: int, s: list, x: list) -> list:
    # 1. 创建两个字典来存储数据
    name_to_max_amount = {}    # 存储每个人的最大红包金额
    name_to_first_index = {}   # 存储每个人第一次抢红包的索引位置
    
    # 2. 遍历所有红包记录,找出每个人的最大红包金额和首次出现位置
    for i, (name, amount) in enumerate(zip(s, x)):
        # 更新最大金额:如果是新名字或者金额更大,就更新
        if name not in name_to_max_amount or amount > name_to_max_amount[name]:
            name_to_max_amount[name] = amount
            
        # 记录首次出现位置:只在第一次见到这个名字时记录
        if name not in name_to_first_index:
            name_to_first_index[name] = i
    
    # 3. 创建唯一名字的人员列表,每个元素包含:名字、最大金额、首次出现索引
    unique_people = [
        (name, name_to_max_amount[name], name_to_first_index[name])
        for name in set(s)  # set(s)去除重复名字
    ]
    
    # 4. 按最大金额降序和首次出现顺序排序
    sorted_people = sorted(unique_people, 
                         key=lambda p: (-p[1], p[2]))  # -p[1]表示金额降序,p[2]表示索引升序
    
    # 5. 只返回排序后的名字列表
    return [person[0] for person in sorted_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'])

四、知识点补充

4.1 enumerate()函数

for i, (name, amount) in enumerate(zip(s, x)):
  • 作用:同时获取列表的索引和值
  • 示例:
s = ["a", "b"]
x = [1, 2]
for i, (name, amount) in enumerate(zip(s, x)):
    print(i, name, amount)
# 输出:
# 0 "a" 1
# 1 "b" 2

4.2 zip()函数

zip(s, x)
  • 作用:将多个列表对应位置的元素打包成元组
  • 示例:
s = ["a", "b"]
x = [1, 2]
list(zip(s, x))  # [("a", 1), ("b", 2)]

4.3 字典操作

name_to_max_amount = {}
if name not in name_to_max_amount:
    name_to_max_amount[name] = amount
  • 作用:存储和更新每个人的最大红包金额
  • 示例:
name = "a"
amount = 100
if name not in name_to_max_amount:  # 如果这个名字还没有记录
    name_to_max_amount[name] = amount  # 添加记录
elif amount > name_to_max_amount[name]:  # 如果新金额更大
    name_to_max_amount[name] = amount  # 更新记录

4.4 set()函数

set(s)
  • 作用:去除列表中的重复元素
  • 示例:
s = ["a", "a", "b", "c", "c"]
unique_names = set(s)  # {"a", "b", "c"}

4.5 sorted()函数

sorted(unique_people, key=lambda p: (-p[1], p[2]))
  • 作用:按指定规则排序
  • 参数说明:
    • unique_people:要排序的列表
    • key:排序依据,这里是一个lambda函数
    • -p[1]:金额取负表示降序排序
    • p[2]:原始索引升序排序
  • 示例:
# 假设数据格式为:(名字,金额,索引)
data = [("a", 100, 0), ("b", 200, 1), ("c", 200, 2)]
sorted(data, key=lambda p: (-p[1], p[2]))
# 输出:[("b", 200, 1), ("c", 200, 2), ("a", 100, 0)]

4.6 列表推导式

[person[0] for person in sorted_people]
  • 作用:从排序后的列表中只提取名字
  • 示例:
sorted_people = [("b", 200, 1), ("c", 200, 2), ("a", 100, 0)]
names = [person[0] for person in sorted_people]  # ["b", "c", "a"]

使用这段代码的关键步骤:

  1. 输入参数:
    • n:参与人数
    • s:名字列表
    • x:对应的红包金额列表
  2. 返回值:
    • 按规则排序后的名字列表
  3. 排序规则:
    • 优先按最大红包金额降序排序
    • 金额相同时按首次抢红包顺序排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值