尝试在列表中查找第二个最大值时出错

Blu*_*lue 4 python list max

我正在尝试编写代码来查找列表的第二个最大值。

我尝试过这样的:

arr = map(int, input().split())
lista = list(arr)
max_value = lista[0]
run = lista[0]
for i in lista:
    if max_value < i:
        max_value = i
for j in lista:
    if run < j and run < max_value:
        run = j
print(run)
Run Code Online (Sandbox Code Playgroud)

第二个最大值和最大值是相同的。我的程序有什么错误?

小智 7

问题

总长DR

    run = lista[0]
    ...
    if run < j and run < max_value:
Run Code Online (Sandbox Code Playgroud)

应该

          v
    run = min(lista)
    ...
                   v
    if run < j and j < max_value:
Run Code Online (Sandbox Code Playgroud)

如何找到问题

1.让代码更简单

使用推导式代替映射-列表构造函数继承

我们可以通过使用推导式而不是一系列的映射和列表构造函数来减少第一行的样板:

arr = map(int, input().split())
lista = list(arr)
Run Code Online (Sandbox Code Playgroud)

变得:

lista = [int(n) for n in input().split()]
Run Code Online (Sandbox Code Playgroud)

向Python询问最大,不要自己做

您的下一个逻辑块是在这里找到列表的最大值。你不需要自己写这段代码,你可以问Python。这将降低代码的复杂性,使问题/错误更容易发现。

max_value = lista[0]
for i in lista:
    if max_value < i:
        max_value = i
Run Code Online (Sandbox Code Playgroud)

变得:

max_value = max(lista)
Run Code Online (Sandbox Code Playgroud)

重命名变量

为了帮助我们的大脑理解发生了什么,让我们澄清变量名称:

lista = [int(n) for n in input().split()]
max_value = max(lista)
run = lista[0]
for j in lista:
    if run < j and run < max_value:
        run = j
print(run)
Run Code Online (Sandbox Code Playgroud)

变得:

user_input = [int(n) for n in input().split()]
max_value = max(user_input)

second_max = user_input[0]
for current_value in user_input:
    if second_max < current_value and second_max < max_value:
        second_max = current_value
        
print(second_max)
Run Code Online (Sandbox Code Playgroud)

2. 查找问题

现在,代码更小,更容易理解,出错的地方也更少。如果有错误,我们不用看很多地方。

怎么了?second_max应该是第二个最大值,但事实并非如此。什么可能导致这种情况?previous_value不应该发生这样的更新。

所以这就是问题可能发生的地方。

    if second_max < current_value and second_max < max_value:
        second_max = current_value
Run Code Online (Sandbox Code Playgroud)

归因是正确的,条件应该是错误的。

这似乎是正确的second_max < current_value,因为我们只想在second_max低于 current_value 时更新(意味着 current 可能是真实second_max值或等于max_value。所以我们需要另一个条件:current_value不应该是max_value,否则second_max可能会设置为max_value

然后,我们看看第二个条件:second_max < max_value。这是我们的错误。

让我们修复这个条件,因为它current_value应该低于max_value。另外,second_max如果第一个值为最大值,则需要将 的初始值设置为最小值。

user_input = [int(n) for n in input().split()]
max_value = max(user_input)

second_max = min(user_input)
for current_value in user_input:
    if second_max < current_value and current_value < max_value:
        second_max = current_value

print(second_max)  # 55
Run Code Online (Sandbox Code Playgroud)

完毕。

替代方案:使用集合、排序和索引

如果您想要列表中的第二个最大值,则对去重列表进行排序并打印列表索引 1 处的元素(例如第二个元素)会更容易。

逐步示例

without_duplicates = {int(n) for n in input().split()}
ordered_without_duplicates = sorted(without_duplicates, reverse=True)
print(ordered_without_duplicates[1])
Run Code Online (Sandbox Code Playgroud)

直线示例

print(sorted({int(n) for n in input().split()}, reverse=True)[1])
Run Code Online (Sandbox Code Playgroud)

与堆

print(heapq.nlargest(2, {int(n) for n in input().split()})[1])
Run Code Online (Sandbox Code Playgroud)