4

I have a list like this:

[1, 2, 5, 2, 7, 3, 9, 5...]

Is there an effective way to find the sum of the 2 largest elements here without:

for i in range():
    for j in range():

I've found this: "Maximum subarray problem"

But I've not completely understand what it does.

Cleb
  • 25,102
  • 20
  • 116
  • 151
  • 1
    so in this case the result would be `9` + `7` ? – Ma0 Feb 07 '18 at 14:40
  • 4
    You can sort array so that biggest numbers are at the start and then sum 2 first elements – myxobek Feb 07 '18 at 14:40
  • Yes, but In my case I have a random list. I get it as inputs and I try to avoid making for in for to check every element –  Feb 07 '18 at 14:42
  • 1
    @TrueBad0ur you should clarify something very important. What is the desired output when the max happens more than once? For example if your list is `[1, 2, 5, 2, 7, 3, 9, 9]`, is your desired answer `9+9` or `9+7`? – FatihAkici Feb 07 '18 at 15:35

6 Answers6

9
sum(sorted([9,8,1,3,4,5,7,0])[-2:])
  1. sorted all elements
  2. get two last elements
  3. sum it
Dmitry Zagorulkin
  • 8,370
  • 4
  • 37
  • 60
  • 1
    or `sum(sorted([9,8,1,3,4,5,7,0], reverse=True)[0:2])` – pault Feb 07 '18 at 14:42
  • 1
    There should be a `O(N)` solution though – user2390182 Feb 07 '18 at 14:42
  • 2
    Or we could use `sum(heapq.nlargest(2, your_list))` – Abdul Niyas P M Feb 07 '18 at 14:45
  • 4
    This is an n log n solution to a linear problem; should not be accepted. Others have already given linear time solutions: read the array once, keep track of the two largest elts, and add them at the end. – Dave Feb 07 '18 at 15:10
  • 4
    @Dave That depends... In terms of pure performance you're right, this is sub-optimal. But, you know, if you don't have millions of numbers, the difference between this solution and a linear one in terms of performance is going to be micro-seconds. The *big* difference however is that this code is way more readable. – ChatterOne Feb 07 '18 at 15:13
9

Here is a linear time solution:

#initialize these to huge negative numbers
largest = -1e10
second_largest = -1e11
l = [9,8,1,3,4,5,7,0]
for item in l:
    if item > largest:
        second_largest = largest
        largest = item
    elif item > second_largest:
        second_largest = item

print(largest+second_largest)
# 17
pault
  • 41,343
  • 15
  • 107
  • 149
3

Here is linear solution:

x = [1, 2, 5, 2, 7, 3, 9, 5]
max1 = -1;
max2 = -1;
for i in range(len(x)):
    if x[i] > max1:
        max2 = max1
        max1 = x[i]
    elif x[i] > max2:
        max2 = x[i]

print(max1+max2)

If your array consists only of positive integers, otherwise consider changing max1, max2 to lowest possible value

myxobek
  • 445
  • 3
  • 10
3

Another O(n) solution, but a bit more pythonic, giving up a bit of performance (iterating 4 times over the list)

l = [1, 2, 5, 2, 7, 3, 9, 5]

# find largest
largest = max(l)
# remove from list
l.remove(largest)
# second largest
largest2 = max(l)
# remove from list
l.remove(largest2)
print(largest+largest2)
>> 16

And to make it a bit more compact, the exact same process in one line:

l = [1, 2, 5, 2, 7, 3, 9, 5]
l.pop(l.index(max(l))) + l.pop(l.index(max(l)))
print(largest+largest2)
>> 16
serkef
  • 319
  • 2
  • 13
  • 1
    You don't need `l.remove(largest2)`, but this works. – pault Feb 07 '18 at 14:59
  • I love this solution. Simple and efficient. If you are not allowed to use the built-in max() and remove(), you can code them, but I love the simplicity of the idea. – FatihAkici Feb 07 '18 at 15:47
  • 1
    This solution might work or not, depending on your definition of "largest". What happens if the largest numbers are duplicate? Should you remove all instances of it, which is another \$O(n)\$ operation, or give `largest * 2` as a result? – ChatterOne Feb 09 '18 at 10:12
  • 1
    Not really, remove will remove the first match of the largest value. next step will find the same max (different index) and will remove it. so quick answer is it will have the same bahaviour just as the rest of the solutions (eg sort, get [:2]). It will result largest * 2 – serkef Feb 13 '18 at 12:39
2

If you don't mind using a library, you can use heapq's nlargest:

import heapq
x = [1, 2, 5, 2, 7, 3, 9, 5]

Then

sum(heapq.nlargest(2, x))

will return

16

Also pandas is an option (but use it only if you import it anyway as it is a rather heavy dependency):

import pandas as pd
pd.Series(x).nlargest(2).sum()

also returns 16

In case you have duplicated maxima, you can use sets:

x = [1, 2, 5, 2, 7, 3, 9, 5, 9]

Then

sum(heapq.nlargest(2, x))

will return

18

as 9 + 9 = 18 and

sum(heapq.nlargest(2, set(x)))

will return

16

as it then calculates 9 + 7 = 16.

Cleb
  • 25,102
  • 20
  • 116
  • 151
1

With unique numbers

This is the simplest way

a = [1, 2, 5, 2, 7, 3, 9, 5]
m1 = max(a)
a.pop(a.index(m1))
m2 = max(a)
print(m1 + m2)

output: 16

If you have more equal number, but you want get rid of them - so that you can add the two biggest DIFFERENT numbers - you can do so:

a = [1, 2, 5, 2, 7, 3, 9, 5]
a = set(a)
m1 = max(a)
a = list(a)
a.pop(a.index(m1))
m2 = max(a)
print(m1 + m2)

The output: 16

If you instead want to add the biggest number in a list, even if they are the same (i.e. 9 and 9), use the first code example and it will work for you.

PythonProgrammi
  • 22,305
  • 3
  • 41
  • 34