views:

146

answers:

2

I came across the following question.

Given an array of n elements and an integer k where k < n. Elements {a0...ak} and {ak+1...an} are already sorted. Give an algorithm to sort in O(n) time and O(1) space.

It does not seem to me like it can be done in O(n) time and O(1) space. The problem really seems to be asking how to do the merge step of mergesort but in-place. If it was possible, wouldn't mergesort be implemented that way? I am unable to convince myself though and need some opinion.

+2  A: 

This seems to indicate that it is possible to do in O(lg^2 n) space. I cannot see how to prove that it is impossible to merge in constant space, but I cannot see how to do it either.

Edit: Chasing references, Knuth Vol 3 - Exercise 5.5.3 says "A considerably more complicated algorithm of L. Trabb-Pardo provides the best possible answer to this problem: It is possible to do stable merging in O(n) time and stable sorting in O(n lg n) time, using only O(lg n) bits of auxiliary memory for a fixed number of index variables.

More references that I have not read. Thanks for an interesting problem.

Further edit: This article claims that the article by Huang and Langston have an algorithm that merges two lists of size m and n in time O(m + n), so the answer to your question would seem to be yes. Unfortunately I do not have access to the article, so I must trust the second hand information. I'm not sure how to reconcile this with Knuth's pronouncement that the Trabb-Pardo algorithm is optimal. If my life depended on it, I'd go with Knuth.

I now see that this had been asked as and earlier Stack Overflow question a number of times. I don't have the heart to flag it as a duplicate.

Huang B.-C. and Langston M. A., Practical in-place merging, Comm. ACM 31 (1988) 348-352

deinst
You are right. I am able to read the paper since I am the University. It seems like it is possible although the technique is quite sophisticated. Thanks for the pointer.
Sid
You can find the paper at CiteSeerX. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.22.8523
Daniel Brückner
@Daniel Thanks. My googling skills need improvement.
deinst
A: 

No it isn't possible, although my job would be much easier if it was :).

You have a O(log n) factor which you can't avoid. You can choose to take it as time or space, but the only way to avoid it is to not sort. With O(log n) space you can build a list of continuations that keep track of where you stashed the elements that didn't quite fit. With recursion this can be made to fit in O(1) heap, but that's only by using O(log n) stack frames instead.

Here is the progress of merge-sorting odds and evens from 1-9. Notice how you require log-space accounting to track the order inversions caused by the twin constraints of constant space and linear swaps.

.     -
135792468
 .   -
135792468
  :  .-
125793468
   : .-
123795468
    #.:-
123495768
     :.-
123459768
      .:-
123456798
       .-
123456789

123456789

There are some delicate boundary conditions, slightly harder than binary search to get right, and even in this (possible) form, and therefore a bad homework problem; but a really good mental exercise.

Update Apparently I am mistaken and there is an algorithm that provides O(n) time and O(1) space. I have downloaded the papers to enlighten myself, and withdraw this answer as incorrect.

Recurse
It is possible for a linked list. The O(log n) comes from somewhere else.
Joshua
I can see how to do it with lg n extra space. I cannot see how to prove that you cannot do better, i.e. that O(lg n) extra space is necessary to keep things linear.
deinst
@Joshua. It's not really fair to say it is possible with a linked list, because the list has O(n) extra pieces of information that make it easier -- the pointers from element to element. If you could afford O(n) extra space, you could do just as well with an array. You allocate a new result array, and just walk your two original arrays, copying the items out in order.
cape1232
@deinst I didn't find it easy, but I did eventually prove to my satisfaction that lg n is the lower bound. That was years ago and unfortunately I no longer have it available. It is however reasonably straight forward to prove that whatever the lower-bound is it is higher than O(1), which is good enough for our purposes here.
Recurse