views:

228

answers:

2

This is not a homework. Just an interesting task :)

Given a complete binary search three represensted by array. Sort the array in O(n) using constant memory.

Example:

Tree:

              8
           /     \
          4       12
         /\       / \
        2  6     10  14
       /\  /\    /\   /\
      1 3 5  7  9 11 13 15

Array: 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15

Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15

+2  A: 

Thinking about the O(1) in-place variant, but for now here's the O(N) solution

An O(N) space solution

If you can use an O(N) output array, then you can simply perform an inorder traversal. Every time you visit a node, add it to the output array.

Here's an implementation in Java:

import java.util.*;
public class Main {
    static void inorder(int[] bst, List<Integer> sorted, int node) {
        if (node < bst.length) {
            inorder(bst, sorted, node * 2 + 1);
            sorted.add(bst[node]);
            inorder(bst, sorted, node * 2 + 2);
        }
    }
    public static void main(String[] args) {
        int[] bst = { 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
        final int N = bst.length;
        List<Integer> sorted = new ArrayList<Integer>();
        inorder(bst, sorted, 0);
        System.out.println(sorted);
        // prints "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]"
    }
}

Attachment

polygenelubricants
As it demands constant memory, I don't think there can be an output array. But inorder traversal is of course the right approach.
inflagranti
Algorithm is correct, however it doesnt work in O(1) space.
phimuemue
This is not enough. After sorting the Array itself should be sorted.
gtikok
@inflagranti: Yes, this is O(n) space. Why can't there be other approaches? In fact, see my answer for one that isn't in-order.
Moron
Yeah, I didn't mean that in-order is the only right approach. But I think it should somehow be possible with in-order traversal.
inflagranti
+16  A: 

It is possible, people calling it homework probably haven't tried solving it yet.

We use the following as a sub-routine:

Given an array a1 a2 ... an b1 b2 .. bn, convert in O(n) time and O(1) space to

b1 a1 b2 a2 ... bn an

A solution for that can be found here: http://arxiv.org/abs/0805.1598

We use that as follows.

Do the above interleaving for the first 2^(k+1) - 2 elements, starting at k=1 repeating for k=2, 3 etc, till you go past the end of array.

For example in your array we get (interleaving sets identified by brackets)

 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15   
[ ][ ]

 4, 8, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15   (k = 1, interleave 2)
[        ][        ]  

 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15   (k = 2, interleave 6)
[                      ][                     ]

 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15   (k = 3, interleave 14)

So the total time is n + n/2 + n/4 + ... = O(n). Space used is O(1).

That this works can be proved by induction.

Moron
That looks good. It still does sound like a homework question though :)
inflagranti
@inflagranti: Have to disagree completely about it being homework, it might sound like one, I agree :-)
Moron
@Moron, "homework question", by definition is "a simplified and useless one". Not necessarily "easy".
Pavel Shved
@Pavel: You made me laugh :-) Not all homework is useless, though. Have you considered that this could actually be useful in some embedded systems? It is hard to judge if anything is useless. Things can be used in ways you cannot even imagine.
Moron
@NickLarsen: Thanks for cleaning up. I removed a sentence which was not required after the cleanup.
Moron