1

write a python code to find out max and second max number from a list using only one loop

Python program to find second largest number in a list

list of numbers - length of list should be at least 2

list1 = [10, 20, 4, 45, 99] 

max=max(list1[0],list1[1]) 
secondmax=min(list1[0],list1[1]) 

for i in range(2,len(list1)): 
   if list1[i]>max: 
      secondmax=max
      max=list1[i] 
   else: 
      if list1[i]>secondmax: 
         secondmax=list1[i] 

print("Second highest number is : ",str(secondmax)) 
ShadowRanger
  • 108,619
  • 9
  • 124
  • 184
Tapas
  • 75
  • 4
  • 1
    What specifically do you need help with? – Carcigenicate Aug 06 '19 at 20:02
  • I don't know what kind of constraints you are working under, but you can pull this off without a loop at all, by sorting the list than pulling out the last two items in the list. – Jason K Lai Aug 06 '19 at 20:10
  • @JasonKLai if he sorts, then the quickest that he can do is nlog(n) and so am assuming sorting is out of the equation. (unless using some bucket/radix sort with O(n) ) then list[-2:] to get the last two numbers – Cryptoharf84 Aug 06 '19 at 20:16
  • 1
    One important thing to know: If the maximum number occurs twice, is the second highest number considered to be the same as the maximum, or is it the next smallest number? `heapq.nlargest` is the Python built-in way to handle the first case, but a solution that addresses the second would have to be custom written. – ShadowRanger Aug 14 '19 at 17:40
  • What's the question? I would use heapq.nlargest, although I don't think the instructor would like that. Do you need to know how to assign/return multiple values at once, from your function? Just "return firstmax, secondmax" (don't use a builtin name for your variable name) – Kenny Ostrom Aug 15 '19 at 19:14
  • @kennyOstrom, using a heap will take nlogn, the answer is attainable in O(n) – Cryptoharf84 Aug 15 '19 at 19:15
  • https://docs.python.org/3.0/library/heapq.html#heapq.nlargest heapify is O(n), docs recommend nlargest for n>1, and nlargest should be O(n log k) which is O(n) where k is a constant. – Kenny Ostrom Aug 15 '19 at 19:17
  • @KennyOstrom. am sorry but n items thus O(n) for total inserts. But each insert requires log(n) time. how can one construct the heap data structure in O(n) ?! – Cryptoharf84 Aug 15 '19 at 19:23
  • @Fadi https://stackoverflow.com/questions/9755721/how-can-building-a-heap-be-on-time-complexity Here found a good link that directly addresses your question. – Kenny Ostrom Aug 15 '19 at 19:32
  • @KennOstrom, thx makes sense now :) – Cryptoharf84 Aug 16 '19 at 15:42

4 Answers4

0

You can also do it without a for loop by calling max() on the list twice - and removing the result of the first call:

list1 = [10, 20, 4, 45, 99]
list1.remove(max(list1))
print(max(list1))

But this is going to be slower than simply using a for loop as you have in your approach, simply because it has to traverse the list twice.

Green Cloak Guy
  • 18,876
  • 3
  • 21
  • 38
  • 1
    The OP does say they can only use one loop; assuming they're not allowed to cheat with hidden loops, `max` and `list.remove` both involve an implicit loop over the `list`, so this is three loops, not one. – ShadowRanger Aug 14 '19 at 17:30
0

If i understood your answer you can try this code(also negative number):

list1 = [99, 20, 4, 10, 45] 

if len(list1) < 2:
    raise Exception ("List size must be >= 2")

first_max=list1[0]
second_max=list1[-1]

#I used the position to avoid the same number(index) for the first and second max
position_first_max=0
position_second_max=len(list1)-1

for idx,item in enumerate(list1):
    if item>first_max:
        second_max=first_max
        position_second_max=position_first_max
        first_max=item
        position_first_max=idx
    else:
        if item>second_max and position_first_max!=idx:
            second_max=item
            position_second_max=idx

print("First highest number is : ",str(first_max))
print("Second highest number is : ",str(second_max))

i tested with different numbers in different position and works.

Hope this helps.

Ferdinando
  • 892
  • 1
  • 8
  • 20
0

one loop without sort or extra data structures:

def find_two_max(lst : list):
    if len(lst) < 2:
        raise Exception ("List size must be >= 2")

    max1=max2=float('-inf')

    for number in lst:
        if number >= max1:
            max2=max1
            max1=number
        elif number > max2:
            max2=number
    return max1, max2

l=[99, 299, 0, 2,3,4,5,1000]
print("The highest two numbers are %s , %s " % find_two_max(l))```
Cryptoharf84
  • 331
  • 1
  • 10
-1

One simple solution is to use built-in Python functions to sort() the list. After sorting the list, you can pull out the second to last item by using the index:

list1 = [10, 20, 4, 45, 99]

list1.sort()
print( 'Highest number is : ', list1[-1] )
print( 'Second highest number is : ', list1[-2] )
Jason K Lai
  • 1,335
  • 3
  • 14
  • I think python uses quick sort or merge sort so O(nlogn). OP is probably looking for O(n) solution – Cryptoharf84 Aug 06 '19 at 20:17
  • You might be right. However, it's not entirely clear since OP only mentioned "using one loop". The way OP described it, it sounded more like a 101 homework question. – Jason K Lai Aug 06 '19 at 20:21
  • Regardless, sorting is obviously overkill since you don't care about the relative ordering of any of the smaller values in the list. – chepner Aug 15 '19 at 19:06