For example, if the numbers are:
30, 12, 49, 6, 10, 50, 13
The array will be:
[10, 6, 30, 12, 49, 13, 50]
<
Assuming the numbers are all distinct, the easiest way is probably to sort the numbers then interleave the first and second halves of the sorted list. This will guarantee the high/low/high/low/high/low/.... pattern that you need.
This algorithm is O(n log n)
which should be efficient enough for most purposes, and may benefit from optimised sorting routines in your standard library.
If the numbers are not distinct, then it is possible that there is no solution (e.g. if the numbers are all equal)
I'm not too knowledgeable about complexity, but here's my idea.
For even length lists:
(For our odd length example,
put 30 aside to make the list even)
1. Split the list into chunks of 2 => [[12,49],[6,10],[50,13]]
2. Sort each chunk => [[12,49],[6,10],[13,50]]
3. Reverse-sort the chunks by
comparing the last element of
one to the first element of
the second => [[12,49],[13,50],[6,10]]
For odd length lists:
4. Place the removed first element in
the first appropriate position => [30,12,49,13,50,6,10]
Haskell code:
import Data.List (sortBy)
import Data.List.Split (chunksOf)
rearrange :: [Int] -> [Int]
rearrange xs
| even (length xs) = rearrangeEven xs
| null (drop 1 xs) = xs
| otherwise = place (head xs) (rearrangeEven (tail xs))
where place x (y1:y2:ys)
| (x < y1 && y1 > y2) || (x > y1 && y1 < y2) = (x:y1:y2:ys)
| otherwise = place' x (y1:y2:ys)
place' x (y1:y2:ys)
| (x < y1 && x < y2) || (x > y1 && x > y2) = (y1:x:y2:ys)
| otherwise = y1 : (place' x (y2:ys))
rearrangeEven = concat
. sortBy (\a b -> compare (head b) (last a))
. map sort
. chunksOf 2
Output:
*Main> rearrange [30,12,49,6,10,50,13]
[30,12,49,13,50,6,10]
*Main> rearrange [1,2,3,4]
[3,4,1,2]
This can be done in O(n):
Of course, this assumes that all elements are distinct, otherwise sometimes it will fail.
Someone posted this question as a dupe to this but the solution over there is better than the accepted solution here so I figured I'd post it here.
Basically the key is for every three numbers where it has to hold that a < b > c
you look at the sequence and swap the biggest number into the center. Then you increment by 2 to get to the next sequence like a < b > c
and do the same thing.
Technically the solution still runs in O(n) like the accepted solution, but it is a better O(n) and it is much simpler because the median of medians algo is tricky to implement. Hopefully anyone who favorited this problem will at least see this solution, I can post the code if anyone is interested.