Sort with two stacks

Problem description
Given an array that is initially stored in one stack, sort it with one additional stack (total 2 stacks).

After sorting the original stack should contain the sorted integers and from top to bottom the integers are sorted in ascending order.


 * Assumptions
 * The given stack is not null.
 * There can be duplicated numbers in the give stack.


 * Example 1
 * Input: [6, 2, 5, 1, 3, 8, 7, 4]
 * Output: [1, 2, 3, 4, 5, 6, 7, 8]


 * Example 2
 * Input: [4, 2, 1, 5, 1, 3, 2, 5]
 * Output: [1, 1, 2, 2, 3, 4, 5, 5]


 * Requirements
 * No additional memory, time complexity = O(n2).

Analysis
First we should note some important properties of transferring data from one stack to another:
 * If we transfer the content from stack 1 to stack 2 (either partially or completely), then the transferred elements will appear in stack 2 in the reverse order of they were in stack 1.
 * Doing a transfer takes O(n) time complexity, where n is the number of elements to be transferred.

Now, in this problem:
 * Stack 1 is the input stack (and the output stack);
 * And we are asked to use stack 2 as a temporary stack.

So we can consider putting data in descending sorted order in stack 2 (the temporary stack), and then transfer everything back to stack 1 (the output stack). This requires us to find the max value in stack 1 each time.

In addition, stack 2 is split into two parts for the two purposes:
 * The left hand side stores the elements that are already sorted in descending order.
 * The right hand side serves as the free space to temporarily store the elements moved from stack 1.


 * Note
 * Let stack 1 has n elements, i.e. the total elements to be sorted.
 * Then, whenever we have m elements sorted on the left of stack 2, the stack 1 will have n-m elements unsorted, and also stack 2 has n-m free spaces on the right.
 * Hence, the n-m spots in stack 2 can be used as the free space to process the remaining elements in stack 1.

So our approach to meet the requirements is as follows:
 * 1) Initially, the number of sorted elements is 0.
 * 2) For each iteration:
 * 3) Locate the maximum value and its index in stack 1. Save them to a helper variable.
 * 4) Transfer all elements after the maximum value index (not including the maximum value index) in stack 1 to stack 2.
 * 5) Then, at this moment, the last element in stack 1 is the maximum element of stack 1. Pop this element from stack 1.
 * 6) Transfer back all the unsorted values from stack 2 to stack 1. Now stack 1 has everything from last step except the popped maximum element.
 * 7) Put this maximum element after the currently sorted elements in stack 2. Increase the number of sorted element by 1.
 * 8) Repeat the iteration above, until all elements in stack 1 are sorted in stack 2. Now stack 2 has all the elements in descending order.
 * 9) Transfer all elements from stack 2 back to stack 1. Then all elements in stack 1 are sorted in ascending order.

Time complexity

 * For n input elements, we have n iterations.
 * Each iteration requires the following steps. In the m-th iteration:
 * Find the max element in stack 1. The time complexity is O(m).
 * Transfer all elements after the index of max element in stack 1 to stack 2. The time complexity is O(m).
 * Pop the max element from stack 1, and save it to a temporary variable. The time complexity is O(1).
 * Put back all unsorted elements from stack 2 to stack 1. The time complexity is O(m-1) = O(m).
 * Put the max element into stack 2. The time complexity is O(1).

So the total time complexity = $$O(n) + O(n-1) + O(n-2) + \dots + O(1) = O(\frac{(n+1)n}{2}) = O(n^2)$$. This satisfies the problem requirement.

Space complexity

 * Stack: We only need to store the temporary stack (stack 2), max value, and max index. The space complexity on memory stack is O(1).


 * Heap: We only have allocated the temporary stack on the heap.
 * For the input stack with n elements, the temporary stack will grow to at most size n.
 * This means that the space complexity on the heap is O(n).

The total space complexity is O(n).