Given an array, a
, of unsorted distinct integers, arrange them so that a[0] < a[1] > a[2] < a[3] > a[4], etc.
So, given the array [3, 1, 7, 5, 9]
, one possible solution is [1, 7, 3, 9, 5]
.
One way to do this would be to sort the array and then take the last part, starting from the end of the array, and interleave it with the first. So, for example:
[3, 1, 7, 5, 9] // original array
[1, 3, 5, 7, 9] // sorted
[1, 9, 3, 7, 5] // rearranged into another possible solution
That’s kind of expensive, though. It takes O(n log n) to sort. It would take O(n) to build the rearranged list into a new array. O(n2) to rearrange in place naively. Perhaps you could do an in-place rearrangement in O(n log n).
There’s a faster solution that takes O(n) to rearrange the numbers. Believe it or not, it’s as simple as scanning the array, checking each pair of numbers to see if they meet the condition (a[i] < a[i+1]
for the even pairs, and a[i] > a[i+1]
for the odd pairs). If a pair doesn’t meet the condition, swap them. Expressed in code, it looks like this:
for i = 0 to n-2
if i is even
// ensure a[i] < a[i+1]
if (a[i] > a[i+1])
swap(a[i], a[i+1])
end if
else
// ensure a[i] > a[i+1]
if (a[i] < a[i+1])
swap(a[i], a[i+1])
end
Really, that’s all there is to the algorithm.
Let me explain why it works.
Given three distinct numbers, (a, b, c)
there are four possible relationships:
- a < b < c
The first condition is met. We know thata < c
, so if we swapb
andc
, we end up witha < c > b
- a < b > c
Both conditions are already met. - a > b < c
Here we have to swapa
andb
to giveb < a ? c
. But we already know thatb < c
, so ifa < c
, swappinga
andc
still gives usb < c > a
. - a > b > c
We know thata > c
, so swappinga
andb
to meet the first condition maintains the second condition, givingb < a > c
.
Okay, so it works with three numbers. Now what happens when you add a fourth? You have a < b > c ? d
. If c < d
, then of course everything’s fine. If c > d
, then we have case 4 above, and we already know that swapping c
and d
will not invalidate the first condition.
Similarly, given a < b > c < d ? e
, if d > e
then we move on. Otherwise we have case 1 above, which we know can be resolved by swapping, without affecting the first condition.
I just love the elegance of this solution. It’s so … neat.