Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most efficient way to sort a number list into alternating low-high-low sequences?

Suppose you are given an unsorted list of positive integers, and you wish to order them in a manner such that the elements alternate as: (less than preceding element), (greater than preceding element), (less than preceding element), etc... The very first element in the output list may ignore the rule. So for example, suppose your list was: 1,4,9,2,7,5,3,8,6.

One correct output would be... 1,9,2,8,3,7,4,6,5

Another would be... 3,4,2,7,5,6,1,9,8

Assume that the list contains no duplicates, is arbitrarily large, and is not already sorted.

What is the most processing efficient algorithm to achieve this?

Now, the standard approach would be to simply sort the list in ascending order first, and then peel elements from the ends of the list in alternation. However, I'd like to know: Is there a more time-efficient way to do this without first sorting the list?

My reason for asking: (read this only if you care)

Apparently this is a question my sister's boyfriend poses to people at job interviews out in San Francisco. My sister asked me the question, and I immediately came up with the standard response. That's what everyone answers. However, apparently one girl came up with a completely different solution that does not require sorting the list, and it appears to work. My sister couldn't explain to me this solution, but the idea has been confounding me since last night. I'd appreciate any help! Thanks!

like image 442
user3151680 Avatar asked Feb 15 '23 06:02

user3151680


1 Answers

You can do this in O(n) by placing each element in turn at the end, or at the penultimate position based on a comparison with the current last element.

For example,

1,4,9,2,7,5,3,8,6
Place 1 at end, current list [1]
4>1 true so place 4 at end, current list [1,4]
9<4 false so place 9 at penultimate position [1,9,4]
2>4 false so place 2 at penultimate [1,9,2,4]
7<4 false so place 7 at penultimate [1,9,2,7,4]
5>4 true so place 5 at end [1,9,2,7,4,5]
3<5 true so place 3 at end [1,9,2,7,4,5,3]
8>3 true so place 8 at end [1,9,2,7,4,5,3,8]
6<8 true so place 6 at end [1,9,2,7,4,5,3,8,6] 

Note that the equality tests alternate, and that we place at the end if the equality is true, or at the penultimate position if it is not true.

Example Python Code

A=[1,4,9,2,7,5,3,8,6]
B=[]
for i,a in enumerate(A):
    if i==0 or (i&1 and a>B[-1]) or (i&1==0 and a<B[-1]):
        B.insert(i,a)
    else:
        B.insert(i-1,a)
print B
like image 52
Peter de Rivaz Avatar answered Apr 28 '23 03:04

Peter de Rivaz