15

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

gtikok
  • 1,119
  • 8
  • 18
  • is it always perfectly balanced? – astorcas Jul 01 '10 at 13:19
  • 3
    @astorcas: even better, it's always complete. – polygenelubricants Jul 01 '10 at 13:23
  • If it is always complete using numbers from 1..N you could just write the values 1..N to the input array. So I'm guessing thats not going to cut it? – Nick Larsen Jul 01 '10 at 13:30
  • 1
    @NickLarsen: That array was just an example, we cannot infer that the numbers are 1..N from that. In any case, assuming that will make the question silly. –  Jul 01 '10 at 13:38
  • @I__: Why are you tagging this as homework? Besides, tagging with 'meta' tags is now frowned upon: http://blog.stackoverflow.com/2010/08/the-death-of-meta-tags/ –  Aug 09 '10 at 18:36
  • @I__: Not sure if you are trying to be funny. Did you even read the first sentence of the question? I suggest you also read:http://meta.stackexchange.com/questions/10811/how-to-ask-and-answer-homework-questions –  Aug 09 '10 at 20:18
  • please dont call me that – Alex Gordon Aug 09 '10 at 20:54
  • @I__: I am not calling you a moron. The Moron you see at the end is my username and is a clickable link to my profile page. –  Aug 09 '10 at 20:58
  • btw i really liked ur answer: http://stackoverflow.com/questions/2336054/find-pointers-from-pointee/2336070#2336070 – Alex Gordon Aug 09 '10 at 21:16
  • @I__: I guess that clears up the situation :-) –  Aug 09 '10 at 21:22

2 Answers2

23

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.

  • That looks good. It still does sound like a homework question though :) – Janick Bernet Jul 01 '10 at 13:20
  • 1
    @inflagranti: Have to disagree completely about it being homework, it might sound like one, I agree :-) –  Jul 01 '10 at 13:26
  • @Moron, "homework question", by definition is "a simplified and useless one". Not necessarily "easy". – P Shved Jul 01 '10 at 13:40
  • 3
    @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. –  Jul 01 '10 at 13:44
  • @NickLarsen: Thanks for cleaning up. I removed a sentence which was not required after the cleanup. –  Jul 01 '10 at 13:51
2

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
  • 376,812
  • 128
  • 561
  • 623
  • 1
    As it demands constant memory, I don't think there can be an output array. But inorder traversal is of course the right approach. – Janick Bernet Jul 01 '10 at 13:09
  • This is not enough. After sorting the Array itself should be sorted. – gtikok Jul 01 '10 at 13:13
  • @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. –  Jul 01 '10 at 13:19
  • 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. – Janick Bernet Jul 01 '10 at 13:23