Reputation: 1943
I have a
list<int> input = //from db of one million records
of 1 million records .
Although I know that using input.OrderByDescending().Skip(1).Take(1)
will solve the problem but if I have 1 million records , it is not a best practice to use OrderBY
.
In this scenario which solution is the best one when we have more records?
Upvotes: 2
Views: 90
Reputation: 11238
This is a solution iterating just once and using LINQ and C# 7 tuples:
var input = Enumerable.Range(0, 101);
var topTwo = input.Aggregate((Biggest: Int32.MinValue, SecondBiggest: Int32.MinValue),
(acc, next) =>
{
if (next > acc.Biggest)
{
acc.SecondBiggest = acc.Biggest;
acc.Biggest = next;
}
if (next < acc.Biggest && next > acc.SecondBiggest)
acc.SecondBiggest = next;
return acc;
});
WriteLine(topTwo.SecondBiggest); // 99
Upvotes: 0
Reputation: 186833
Scan the list while tracking the max
, as well as max2
and you'll get O(N)
versus O(N * log(N))
time complexity:
// Maximum value
int max = Math.Max(input[input.Count - 1], input[input.Count - 2]);
// Second greatest
int max2 = Math.Min(input[input.Count - 1], input[input.Count - 2]);
// i >= 0: Comparing with 0 is slightly faster then with Count
for (int i = input.Count - 3; i >= 0; --i) {
int v = input[i];
if (v >= max) {
max2 = max;
max = v;
}
else if (v > max2)
max2 = v;
}
Edit: In case duplicates should be ignored (see comments below) and thus the answer for [1, 2, 3, 4, 4, 4, 4]
should be 3
, not 4
:
// Maximum value
int max = int.MinValue;
// Second greatest
int max2 = int.MinValue;
// i >= 0: Comparing with 0 is slightly faster then with Count
for (int i = input.Count - 1; i >= 0; --i) {
int v = input[i];
if (v > max) {
max2 = max;
max = v;
}
else if (v > max2 && v != max)
max2 = v;
}
Upvotes: 4
Reputation: 17964
You can do it by keeping track of the next max and iterating once through the list.
int max = Int32.MinValue;
int nextMax = Int32.MinValue;
for(int i=0; i<list.Count(); i++)
{
if(list[i] > max)
{
nextMax = max;
max = list[i];
}
else if(list[i] > nextMax)
{
nextMax = list[i];
}
}
Upvotes: 2
Reputation: 11238
If your list contains only distinct values, you can also do:
var max = input.Max();
input.Remove(max);
var result = input.Max();
Upvotes: 2