I'm trying to pass a pre-written test with focus on performance. What is the most efficient way to return the sum of the two highest numbers in a List of int? I have tried the following and according to the test it wasn't fast enough when it comes to larger lists:
1. list.Sort();
list.Reverse();
return list[0] + list[1];
2. return list.OrderByDescending(num => num).FirstOrDefault() + list.OrderByDescending(num => num).Skip(1).FirstOrDefault();
3. var secondHighest = list.Distinct()
.OrderByDescending(i => i)
.Skip(1)
.First();
return list.Max() + secondHighest;
Any straightforward sorting operation would be O(n*log(n)) ( OrderBy(Descending)
, Sort
) at best (on random data) though current task is achievable in O(n) with a simple loop (assuming there are at least 2 items in the list of course, for the case when there are 2 or less elements just return list.Sum()
):
var first = int.MinValue;
var second = int.MinValue;
foreach(var i in list)
{
if(i > first)
{
second = first;
first = i;
}
else if(i > second)
{
second = i;
}
}
var result = first + second;
Also it worth noting that there can be implementation depended LINQ optimizations for some of cases like combination of OrderBy(Descending)
with operators like First(OrDefault)
or possibly Take
(see one , two ).
Well, I'm proposing this algorithm:
highest = 0
highestSet = false
secondHighest = 0
secondHighestSet = false
foreach item in list
if item >= highest or !highestSet
if highestSet
secondHighest = highest
highestSet = true
highest = item
else if item >= secondHighest or !secondHighestSet
secondHighestSet = true
secondHighest = item
return highest + secondHighest
Input set of [3, 2, 3, 2], it will return 6. This is O(n) time complexity.
For a set of [3], it will return 3.
LINQ can be a very good solution for it.
long sum = 0;
if(list.Count > 1)
sum = list.OrderByDescending(z=>z).Take(2).Sum();
else
sum = list.Sum();
You can try this simple way:
list.Sort();
list.Reverse();
var secondHighest=list.Take(2).Sum();
return secondHighest;
or
list=list.OrderByDescending(o=>o).ToList();
var secondHighest=list.Take(2).Sum();
return secondHighest;
At first, it sorts your list, then reverses it , now you have descending sorted list , than it will take 2 highest elements and aggregate them .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.