如何迭代筛选列表局部极值至仅剩一个元素(非Numpy实现)
局部极值迭代筛选玩家获胜者问题修复
问题需求
从玩家名:数值组成的列表中,通过多轮迭代筛选局部极小值/极大值,直到只剩一个获胜者,规则如下:
- 每轮先筛选局部极小值,若筛选后元素数量>1,再筛选局部极大值
- 统计完成的迭代轮数
- 局部极值规则:
- 极小值:首元素仅小于下一个元素则保留;末元素仅小于前一个元素则保留;中间元素需小于前后两个元素
- 极大值:规则相反(首元素大于下一个保留,末元素大于前一个保留,中间元素大于前后两个)
现有问题
现有代码无法完成多轮迭代,局部极小值筛选后无法正确执行极大值筛选,示例输入输出不符:
- 实际输出:
Kunglao:20 is selected in round: 1 - 预期输出:经过2轮迭代,获胜者为
Fujin:101
现有代码
def select_mid(players: str): player_list = players.split() # Split the input string into individual name:identifier pairs ranks = [int(pair.split(":")[1]) for pair in player_list] # Extract and convert the identifiers to integers minima_list = [] maxima_list = [] round = 0 for i in range(1, len(ranks)): if len(player_list) > 1: # Here search is "current_rank < prev_rank and current_rank < next_rank" prev_rank, current_rank, next_rank = ranks[i-1], ranks[i], ranks[i] if i == len(ranks) - 1 else ranks[i+1] if current_rank < prev_rank and current_rank < next_rank: minima_list.append(player_list[i]) player_list = minima_list #Here search is "current_rank > prev_rank and current_rank > next_rank" if current_rank > prev_rank and current_rank > next_rank: maxima_list.append(player_list[i]) player_list = maxima_list round +=1 elif len(player_list) == 1: selection = player_list[0] return f"{selection} is selected in round: {round} " # Example inputs: result = select_mid("Hulk:70 Kitana:83 Kunglao:20 goro:68 e:50 f:67 DE:40 Ef:177 Sindel:130 Konami:179 Fifa:95 ps:123 Fujin:101 name:134 Hola:89 Amari:205 Shakur:175 Rambo:303 Clay:33 Sheba:725 jaki:51") print(result)
问题分析
现有代码核心问题:
- 错误使用单轮
for循环而非多轮迭代,无法持续缩小列表直到只剩一个元素 - 局部极值筛选逻辑错误:未正确处理首/末元素的特殊规则,中间元素判断不符合要求
- 筛选后直接覆盖原列表的时机错误,导致后续筛选基于不完整数据
- 极小值与极大值筛选嵌套逻辑错误,同一元素不可能同时是两种极值
修复后的代码
def select_mid(players: str): player_list = players.split() round_count = 0 # 避免使用Python内置关键字round作为变量名 def get_local_extrema(items, is_minima): """提取局部极值的工具函数,is_minima为True时找极小值,False找极大值""" if len(items) <= 1: return items.copy() extrema = [] ranks = [int(pair.split(":")[1]) for pair in items] # 处理首元素 first_rank = ranks[0] next_rank = ranks[1] if is_minima: if first_rank < next_rank: extrema.append(items[0]) else: if first_rank > next_rank: extrema.append(items[0]) # 处理中间元素 for i in range(1, len(items)-1): current_rank = ranks[i] prev_rank = ranks[i-1] next_rank = ranks[i+1] if is_minima: if current_rank < prev_rank and current_rank < next_rank: extrema.append(items[i]) else: if current_rank > prev_rank and current_rank > next_rank: extrema.append(items[i]) # 处理末元素 last_rank = ranks[-1] prev_last_rank = ranks[-2] if is_minima: if last_rank < prev_last_rank: extrema.append(items[-1]) else: if last_rank > prev_last_rank: extrema.append(items[-1]) return extrema # 多轮迭代直到只剩一个元素 while len(player_list) > 1: round_count += 1 # 第一步:筛选局部极小值 minima_list = get_local_extrema(player_list, is_minima=True) player_list = minima_list # 如果筛选后仍有多个元素,继续筛选局部极大值 if len(player_list) > 1: maxima_list = get_local_extrema(player_list, is_minima=False) player_list = maxima_list return f"{player_list[0]} is selected in round: {round_count} " # 示例输入测试 result = select_mid("Hulk:70 Kitana:83 Kunglao:20 goro:68 e:50 f:67 DE:40 Ef:177 Sindel:130 Konami:179 Fifa:95 ps:123 Fujin:101 name:134 Hola:89 Amari:205 Shakur:175 Rambo:303 Clay:33 Sheba:725 jaki:51") print(result)
关键修复点
- 多轮迭代逻辑:使用
while循环持续处理列表,直到只剩一个元素 - 工具函数封装:将极值筛选逻辑封装为
get_local_extrema,清晰处理首/中/末元素的不同规则,避免重复代码 - 变量名规范:将
round改为round_count,避免与Python内置函数冲突 - 正确迭代流程:每轮先执行极小值筛选,若结果长度>1再执行极大值筛选,每轮结束后更新列表
- 严格极值判断:完全按照规则处理首元素(仅与下一个比较)、末元素(仅与前一个比较)、中间元素(与前后都比较)
测试结果
运行示例输入后,输出为:Fujin:101 is selected in round: 2 ,与预期一致。
内容的提问来源于stack exchange,提问作者Albert Lutakome
相关产品推荐
相关产品推荐

