views:

498

answers:

4

I have an array of ints. I want to get the second highest number in that array. Is there an easy way to do this?

+2  A: 

You don't specify if you want to do this with the minimum complexity.

Assuming your array is unsorted, please see: How to find the kth largest element in an unsorted array of length n in O(n)?

To find Kth largest element in an unsorted array: Build a max heap in O(n). Now remove k elements from the heap; where each removal costs log(n) time to maintain the heap. Total time complexity = O(n + klogn)

To understand building Max heap in O(n) see Binary heap

Mitch Wheat
How can the total complexity be O(k log n) when there's an O(n) step?
Jon Skeet
Who cares about toal complexity or binary heaps when you can do what you want simply with LINQ? :D
RCIX
Thanks Jon. The initial step to build the heap is O(n); subsequent removes are each O(logn).
Mitch Wheat
@RCIX: yeah who cares about complexity...until you come up against a few thousans elements and you happen to be using an O(n^2) algorithm!
Mitch Wheat
True, but i say only optimize for that if it matters :)
RCIX
@RCIX: it never matters until it's too late! :)
Mitch Wheat
+4  A: 

Yes, have 2 vars (first and second) passthrough the array and each time compair what you get with this two cells (always putting the highest on first and the 2nd highest on second) with one pass you will get the 2nd higher on the second var.

Dani
+6  A: 

You could sort the array and choose the item at the second index, but the following O(n) loop will be much faster.

int[] myArray = new int[] { 0, 1, 2, 3, 13, 8, 5 };
int largest = int.MinValue;
int second = int.MinValue;
foreach (int i in myArray)
{
    if (i > largest)
    {
     second = largest;
     largest = i;
    }
    else if (i > second)
     second = i;
}

System.Console.WriteLine(second);
Gene Goykhman
you may as well initialise largest and second to int.MinValue and make no assumptions ;)
Martin
+7  A: 

Try this (using LINQ):

int secondHighest = (from number in numbers
                     orderby number descending
                     select number).Skip(1).First();
RCIX
+1..LOL..Thats a good one.
Luke101
You should be able to replace `.ToList()[0]` with `.First()`.
Fredrik Mörk
Didn't think of that, thanks!
RCIX
Anyone able to comment on how efficient this is compared to a raw loop method like @Gene Goykhman's version?
mrnye
It's not as efficient, but unless you're sorting a MASSIVE list of ints, this is the best way to go. The best way to go is to performance benchmark then only speed up the bottlenecks. And you only need to do that if it's actually running slow.
RCIX
Does LINQ not have a partial sort? Yes, optimisation should be concentrated at bottlenecks. But if you have a choice of algorithms, and the code for each is about as complicated, you aren't obliged to deliberately pick the slower one in order to avoid "premature optimisation" ;-)
Steve Jessop
Good point. I don't know of any way to partially sort lists with linq, but it would be a good question :)
RCIX