Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort a "sorted" array

  1. Suppose given an array of size n, with sorted values.
  2. In iteration i, a new random-generated value is given, and inserted into the end of the array.
  3. The array is then resorted, and discard the least value item.
  4. After iteration n, the retained array will contain the largest value items.

For example, in Java syntax, it will be something like:

List l = new ArrayList();
l.add(new Integer(2));
l.add(new Integer(3));
l.add(new Integer(6));
l.add(new Integer(9));

Random rand = new Random();
for (int i=0; i < n; i++) {
  l.add(new Integer(rand.nextInt(1000)));
}    
Collections.sort(l);
l.remove(0);

But it seems it's inefficient. Any better algorithm?

like image 678
developer.cyrus Avatar asked Aug 15 '26 08:08

developer.cyrus


2 Answers

Use a binary insert (works like a binary search) for the new value. Discard the smallest. Should be quite fast.

By the way - this can be implemented as a handy extension method:

private static int GetSortedIndex( this IList list, IComparer comparer, object item, int startIndex, int endIndex )
{
  if( startIndex > endIndex )
  {
    return startIndex;
  }
  var midIndex = startIndex + ( endIndex - startIndex ) / 2;
  return comparer.Compare( list[midIndex], item ) < 0 ?
    GetSortedIndex( list, comparer, item, midIndex + 1, endIndex ) :
    GetSortedIndex( list, comparer, item, startIndex, midIndex - 1 );
}

public static void InsertSorted( this IList list, IComparer comparer, object item )
{
  list.Insert( list.GetSortedIndex( comparer, item ), item );
}

Java Equivalent

public static void main(String[] args)
{
   List l = new ArrayList();
   l.add(new Integer(2));
   l.add(new Integer(3));
   l.add(new Integer(6));
   l.add(new Integer(9));

   Random rand = new Random();
   for (int i=0; i < 10; i++) {
       Integer rnd = new Integer(rand.nextInt(1000));
       int pos = Collections.binarySearch(l,rnd);
       if(pos < 0) pos = ~pos;
       l.add(pos,rnd);
   }    
   System.out.println(l);
}
like image 191
tanascius Avatar answered Aug 16 '26 22:08

tanascius


Use a TreeSet instead of a List, it'll maintain the order such that such that the largest value will always be at SortedSet#last(). If using 1.6+ you can use NavigableSet methods; pollLast() will return and remove the highest value.

NavigableSet<Integer> set = new TreeSet<Integer>();

//... setup data

Integer highest = set.pollLast();

set.add(rand.nextInt(1000));

Integer newHighest = set.pollLast();
like image 29
Gareth Davis Avatar answered Aug 16 '26 22:08

Gareth Davis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!