1

when I run the code, it returns 9 but the answer should be 10

       list = [9, 6, 4, 10, 13, 2, 3, 5]
        max = list[0]
        second_last = list[0]
        for x in list:
            if x > max:
                max = x
            # Here is an issue with this statement 
            if x > second_last and x != max:
                second_last = x
        print(second_last)
  • 1
    Don't use `list` and `max` as names for your own variables. You overwrite the built-ins ([`list`](https://docs.python.org/3/library/functions.html#func-list), [`max`](https://docs.python.org/3/library/functions.html#max)) with the same name. – Matthias Feb 15 '22 at 08:25
  • 2
    Does this answer your question? [Get the second largest number in a list in linear time](https://stackoverflow.com/questions/16225677/get-the-second-largest-number-in-a-list-in-linear-time) – Kelly Bundy Feb 15 '22 at 08:33

5 Answers5

2

Once you have a new max, just push the old max down to the second max

list = [9, 6, 4, 10, 13, 2, 3, 5]
max = float('-inf')
second_last = float('-inf')
for x in list:
    if x > max:
        second_last = max
        max = x
    elif x > second_last and x != max:
        second_last = x

print(second_last)
Tobi208
  • 1,306
  • 10
  • 17
1

Try this:

l = [9, 6, 4, 10, 13, 2, 3, 5]

_max = max(l)
_second = min(l)

for num in l:
    if _second < num < _max:
        _second = num
            
print(_second)
N1CK145
  • 59
  • 1
  • 11
  • 1
    Could also use `if _second < num < _max:`. – Kelly Bundy Feb 15 '22 at 08:52
  • That chained comparison is btw probably not just shorter/clearer, but also faster. Because `_max > num` is very likely true, causing two comparisons most of the time, while `_second < num` is very likely false, so if you test that first, most of the time you need just one comparison. – Kelly Bundy Feb 15 '22 at 08:56
1
x:      max and second_last
9:      9 and 9
6:      9 and 9
4:      9 and 9
10:     10 and 9
13:     13 and 9 <<<
2:      13 and 9
3:      13 and 9
5:      13 and 9

You are essentially losing information about second_last, which is held by max until it is replaced by x when x > max. Whenever max is updated, technically second_last should also be updated, as the old max is the new second_last.

Notice that if the first if statement is satisfied, the second cannot be satisfied, so max and second_last are never updated simultaneously.

So, unless there is some value y further down in the iteration such that second_last < y != max - Eg: list = [9, 12, 10], y = 10 -, your code will produce incorrect outputs. So, your code never updates second_last when the sequence is strictly increasing.

Here is a fix for your code:

list = [9, 6, 4, 10, 13, 2, 3, 5]
max = list[0]
second_last = list[0]
for x in list:
    if x > max:
        second_last = max # add this line
        max = x 
    elif x > second_last and x != max:
        second_last = x
print(second_last)

Besides, it is a good idea, not to assume the list is non-empty.

aryan
  • 51
  • 8
0
list = [9, 6, 4, 10, 13, 2, 3, 5]
max = list[0]
second_last = list[0]
for x in list[1:]:
    if x > max:
        second_last = max
        max = x
    elif x < max and x > second_last:
        second_last = x
print(second_last)
linuxias
  • 306
  • 2
  • 10
-1

You could build a new list containing 2 elements (max and second_last):

lst = [9, 6, 4, 10, 13, 2, 3, 5]
# results[0] = max; results[1] = second_last
results = [float("-inf"), float("-inf")] # initialise negative infinite!

for item in lst:
    if item > results[0]:
        results = [item, results[0]]

print(results)
# OR
max_value, second_last = results
print(max_value)
print(second_last)

Out:

[13, 10]
13
10

Easiest approach would be using built-in sort:

results = sorted(lst, reverse=True)
print(results[:2])
>>> [13, 10]

Node: list and max are Python built-ins, do not use them as variable names.

Maurice Meyer
  • 17,279
  • 4
  • 30
  • 47