J'apprends le python et les méthodes simples de gestion des listes sont présentées comme un avantage. Parfois c'est le cas, mais regardez ceci:
>>> numbers = [20,67,3,2.6,7,74,2.8,90.8,52.8,4,3,2,5,7]
>>> numbers.remove(max(numbers))
>>> max(numbers)
74
Un moyen très facile et rapide d’obtenir le deuxième plus grand nombre à partir d’une liste. Sauf que le traitement facile des listes permet d'écrire un programme qui parcourt la liste deux fois, pour trouver le plus grand, puis le deuxième. C'est également destructeur: j'ai besoin de deux copies des données si je veux conserver l'original. Nous avons besoin:
>>> numbers = [20,67,3,2.6,7,74,2.8,90.8,52.8,4,3,2,5,7]
>>> if numbers[0]>numbers[1]):
... m, m2 = numbers[0], numbers[1]
... else:
... m, m2 = numbers[1], numbers[0]
...
>>> for x in numbers[2:]:
... if x>m2:
... if x>m:
... m2, m = m, x
... else:
... m2 = x
...
>>> m2
74
Ce qui ne parcourt la liste qu'une seule fois, mais n'est pas concis et clair comme dans la solution précédente.
Alors: y a-t-il un moyen, dans des cas comme celui-ci, d’avoir les deux? La clarté de la première version, mais le single de la seconde?
Puisque @OscarLopez et moi-même avons des opinions différentes sur ce que signifie le deuxième plus gros, je posterai le code conformément à ma vision et conformément au premier algorithme fourni par le demandeur.
def second_largest(numbers):
count = 0
m1 = m2 = float('-inf')
for x in numbers:
count += 1
if x > m2:
if x >= m1:
m1, m2 = x, m1
else:
m2 = x
return m2 if count >= 2 else None
(Remarque: l'infini négatif est utilisé ici au lieu de None
puisque None
a un comportement de tri différent en Python 2 et 3 - voir Python - Trouver le deuxième plus petit nombre ; un contrôle du nombre d'éléments dans numbers
permet de s'assurer que l'infini négatif a gagné ne sera pas renvoyé lorsque la réponse réelle sera indéfinie.)
Si le maximum se produit plusieurs fois, il se peut également que ce soit le deuxième plus grand. Une autre chose à propos de cette approche est que cela fonctionne correctement s'il y a moins de deux éléments; alors il n'y a pas de deuxième plus grand.
Effectuer les mêmes tests:
second_largest([20,67,3,2.6,7,74,2.8,90.8,52.8,4,3,2,5,7])
=> 74
second_largest([1,1,1,1,1,2])
=> 1
second_largest([2,2,2,2,2,1])
=> 2
second_largest([10,7,10])
=> 10
second_largest([1,1,1,1,1,1])
=> 1
second_largest([1])
=> None
second_largest([])
=> None
Mettre à jour
J'ai restructuré les conditionnels pour améliorer considérablement les performances. presque par 100% dans mes tests sur des nombres aléatoires. La raison en est que, dans la version d'origine, la Elif
était toujours évaluée dans l'éventualité probable que le nombre suivant ne soit pas le plus grand de la liste. En d’autres termes, pour pratiquement chaque nombre de la liste, deux comparaisons ont été effectuées, alors qu’une comparaison suffit généralement - si le nombre n’est pas plus grand que le deuxième plus grand, il n’est pas plus grand que le plus grand.
Vous pouvez utiliser le module heapq :
>>> el = [20,67,3,2.6,7,74,2.8,90.8,52.8,4,3,2,5,7]
>>> import heapq
>>> heapq.nlargest(2, el)
[90.8, 74]
Et à partir de là ...
Vous pouvez toujours utiliser sorted
>>> sorted(numbers)[-2]
74
Essayez la solution ci-dessous, elle est O(n)
et il stockera et retournera le deuxième plus grand nombre dans la variable second
. Notez que si tous les éléments de numbers
sont égaux, ou si numbers
est vide ou s'il contient un seul élément, la variable second
se retrouvera avec une valeur de None
- ceci est correct, car il n'y a pas de "seconde plus grand "élément.
Attention : ceci trouve la valeur "deuxième maximum". S'il y a plus d'une valeur qui est "premier maximum", elles seront toutes traitées comme le même maximum - dans ma définition, dans une liste telle que celle-ci: [10, 7, 10]
la bonne réponse est 7
.
def second_largest(numbers):
first, second = None, None
for n in numbers:
if n > first:
first, second = n, first
Elif first > n > second:
second = n
return second
Voici quelques tests:
second_largest([20,67,3,2.6,7,74,2.8,90.8,52.8,4,3,2,5,7])
=> 74
second_largest([1,1,1,1,1,2])
=> 1
second_largest([2,2,2,2,2,1])
=> 1
second_largest([10, 7, 10])
=> 7
second_largest([1,1,1,1,1,1])
=> None
second_largest([1])
=> None
second_largest([])
=> None
>>> l = [19, 1, 2, 3, 4, 20, 20]
>>> sorted(set(l))[-2]
19
L'algorithme quickselect , O(n) cousin de quicksort, fera ce que vous voulez. Quickselect a une performance moyenne O (n). Les performances dans le pire des cas sont O (n ^ 2), tout comme le tri rapide, mais c'est rare, et des modifications apportées à quickselect réduisent les performances dans le pire des cas à O (n).
L'idée de quickselect est d'utiliser le même pivot, une idée plus basse et plus élevée du tri rapide, mais d'ignorer ensuite la partie inférieure et d'ordonner davantage la partie supérieure.
Pourquoi compliquer le scénario? C'est très simple et direct
Voici un code
mlist = [2, 3, 6, 6, 5]
mlist = list(set(mlist))
print mlist[-2]
Si cela ne vous dérange pas d'utiliser numpy (import numpy as np
):
np.partition(numbers, -2)[-2]
vous donne le 2e élément le plus volumineux de la liste avec le pire cas garanti O(n) temps d'exécution .
Les méthodes partition(a, kth)
renvoient un tableau dans lequel l'élément k
th est identique à celui qu'il aurait dans un tableau trié, tous les éléments précédents sont plus petits et tous les éléments suivants sont plus grands.
il y a de bonnes réponses ici pour le type ([]), au cas où quelqu'un aurait besoin de la même chose sur un type ({}), c'est ici,
def secondLargest(D):
def second_largest(L):
if(len(L)<2):
raise Exception("Second_Of_One")
KFL=None #KeyForLargest
KFS=None #KeyForSecondLargest
n = 0
for k in L:
if(KFL == None or k>=L[KFL]):
KFS = KFL
KFL = n
Elif(KFS == None or k>=L[KFS]):
KFS = n
n+=1
return (KFS)
KFL=None #KeyForLargest
KFS=None #KeyForSecondLargest
if(len(D)<2):
raise Exception("Second_Of_One")
if(type(D)!=type({})):
if(type(D)==type([])):
return(second_largest(D))
else:
raise Exception("TypeError")
else:
for k in D:
if(KFL == None or D[k]>=D[KFL]):
KFS = KFL
KFL = k
Elif(KFS == None or D[k] >= D[KFS]):
KFS = k
return(KFS)
a = {'one':1 , 'two': 2 , 'thirty':30}
b = [30,1,2]
print(a[secondLargest(a)])
print(b[secondLargest(b)])
Juste pour le plaisir, j'ai essayé de le rendre convivial xD
O (n): La complexité temporelle d'une boucle est considérée comme O(n) si les variables de la boucle sont incrémentées/décrémentées d'une quantité constante. Par exemple, les fonctions suivantes ont une complexité temporelle de O(n).
// Here c is a positive integer constant
for (int i = 1; i <= n; i += c) {
// some O(1) expressions
}
Pour trouver le deuxième plus grand nombre, j’ai utilisé la méthode ci-dessous pour trouver d’abord le plus grand nombre, puis rechercher dans la liste si c’est là ou non.
x = [1,2,3]
A = list(map(int, x))
y = max(A)
k1 = list()
for values in range(len(A)):
if y !=A[values]:
k.append(A[values])
z = max(k1)
print z
Cela peut être fait en temps [N + log (N) - 2], ce qui est légèrement meilleur que la limite supérieure libre de 2N (ce qui peut aussi être pensé à O(N)).
L'astuce consiste à utiliser des appels binaires récursifs et l'algorithme "tournoi de tennis". Le gagnant (le plus grand nombre) apparaîtra après tous les «matchs» (prend N-1 fois), mais si nous enregistrons les «joueurs» de tous les matchs, et parmi eux, regroupez tous les joueurs que le gagnant a battus, le deuxième plus grand nombre sera le plus grand nombre de ce groupe, c’est-à-dire le groupe des «perdants».
La taille de ce groupe de «perdants» est log (N) et, encore une fois, nous pouvons révoquer les appels binaires récursifs pour trouver le plus grand des perdants, ce qui prendra du temps [log (N) - 1]. En fait, nous pouvons simplement balayer linéairement le groupe des perdants pour obtenir la réponse également, le budget-temps est le même.
Voici un exemple de code python:
def largest(L):
global paris
if len(L) == 1:
return L[0]
else:
left = largest(L[:len(L)//2])
right = largest(L[len(L)//2:])
pairs.append((left, right))
return max(left, right)
def second_largest(L):
global pairs
biggest = largest(L)
second_L = [min(item) for item in pairs if biggest in item]
return biggest, largest(second_L)
if __== "__main__":
pairs = []
# test array
L = [2,-2,10,5,4,3,1,2,90,-98,53,45,23,56,432]
if len(L) == 0:
first, second = None, None
Elif len(L) == 1:
first, second = L[0], None
else:
first, second = second_largest(L)
print('The largest number is: ' + str(first))
print('The 2nd largest number is: ' + str(second))
def SecondLargest(x):
largest = max(x[0],x[1])
largest2 = min(x[0],x[1])
for item in x:
if item > largest:
largest2 = largest
largest = item
Elif largest2 < item and item < largest:
largest2 = item
return largest2
SecondLargest([20,67,3,2.6,7,74,2.8,90.8,52.8,4,3,2,5,7])
Vous pouvez trouver le 2ème plus grand de l'une des manières suivantes:
Option 1:
numbers = set(numbers)
numbers.remove(max(numbers))
max(numbers)
Option 2:
sorted(set(numbers))[-2]
Un moyen simple:
n=int(input())
arr = set(map(int, input().split()))
arr.remove(max(arr))
print (max(arr))
Pour donner une réponse plus générale à la réponse acceptée, voici l’extension permettant d’obtenir la kème valeur la plus grande:
def kth_largest(numbers, k):
largest_ladder = [float('-inf')] * k
count = 0
for x in numbers:
count += 1
ladder_pos = 1
for v in largest_ladder:
if x > v:
ladder_pos += 1
else:
break
if ladder_pos > 1:
largest_ladder = largest_ladder[1:ladder_pos] + [x] + largest_ladder[ladder_pos:]
return largest_ladder[0] if count >= k else None
Objectif : trouver le deuxième plus grand nombre à partir de l'entrée.
Entrée : 5 2 3 6 6 5
Sortie : 5
*n = int(raw_input())
arr = map(int, raw_input().split())
print sorted(list(set(arr)))[-2]*
Vous pouvez aussi essayer ceci:
>>> list=[20, 20, 19, 4, 3, 2, 1,100,200,100]
>>> sorted(set(list), key=int, reverse=True)[1]
100
La plupart des réponses précédentes sont correctes mais voici un autre moyen!
Notre stratégie consiste à créer une boucle avec deux variables first_highest et second_highest. Nous parcourons les nombres et si notre valeur current_value est supérieure au premier_highest, nous définissons ensuite second_highest comme étant first_highest et ensuite le second_highest est le nombre actuel. Si notre nombre actuel est supérieur à second_highest, nous définissons ensuite second_highest identique au nombre actuel
#!/usr/bin/env python3
import sys
def find_second_highest(numbers):
min_integer = -sys.maxsize -1
first_highest= second_highest = min_integer
for current_number in numbers:
if current_number > first_highest:
second_highest = first_highest
first_highest = current_number
Elif current_number > second_highest:
second_highest = current_number
return second_highest
print(find_second_highest([80,90,100]))
n=input("Enter a list:")
n.sort()
l=len(n)
n.remove(n[l-1])
l=len(n)
print n[l-1]