(disclaimer: for school)
As far as I know, recursively splitting a linked list, then sending it off to another function to merge is O(nlogn) time and O(n) space. Is it possible to do mergesort on linked list with O(nlogn) time and O(1) space complexity? How would you go about doing this?
ANY HELP APPRECIATED
PS: to make sure that the traditional mergesort is space complexity 0(n), this is an example of 0(n), right? How would it be changed for O(1) space?
void sortTrack() {
Node merge = this.head;
this.head = Node (merge);
}
public Node mergeSort(Node head){
if ((head == null)||(head.next == null)){
return head;
}
Node left = head;
Node right = head.next;
while((right != null) && right.next != null){
head = head.next;
right = right.next.next;
}
right = head.next;
head.next = null;
return merge(mergeSort(left), mergeSort(right));
}
public Node merge(Node left, Node right){
Node head = new Node ();
Node temp = head;
while((left != null) && (right !=null)){
if(left <= right ){
temp.next = left;
temp = left;
left = left.next;
}
else{
temp.next = right;
temp = right;
right = right.next;
}
}
if(right == null)
temp.next = left;
else
temp.next = right;
return head.next;
}
The Space Complexity of Merge Sort is O(log N) where N is the number of nodes in the linked list. This is because Merge sort algorithm is recursive, it requires O(log N) stack space for linked list cases.
Yes, it's possible to perform an in-place merge sort. That does not mean it doesn't require any extra memory, since the recursion still takes O(lg n) stack space (just like quicksort).
The list of size N is divided into a max of Logn parts, and the merging of all sublists into a single list takes O(N) time, the worst-case run time of this algorithm is O(nLogn) Best Case Time Complexity: O(n*log n) Worst Case Time Complexity: O(n*log n) Average Time Complexity: O(n*log n) The time complexity of ...
MergeSort algorithm takes three steps: Divide step computes mid position of sub-array and it takes constant time O(1). Conquer step recursively sort two sub arrays of approx n/2 elements each. Combine step merges a total of n elements at each pass requiring at most n comparisons so it take O(n).
Your recursive approach requires Θ(log n) extra space, since you'll have Θ(log n) calls on the stack when you're all the way down to merge-sorting a singleton-list.
To reduce it to O(1) extra space, you'll need to change from a recursive "top-down" approach, where you split the list into two large sublists, sort them, and merge the results — giving you a recursive depth of Θ(log n) — to an iterative "bottom-up" approach where you first sort all the singleton-lists, then all the pairs (the first and second elements, then the third and fourth, etc.), then all the quartets (the first through fourth elements, then the fifth through eighth, etc.) — giving you Θ(log n) passes through the list. Each pass takes Θ(n) time, so the total time is still Θ(n log n).
So overall, you'll have three methods:
Node merge(Node listA, Node listB)
, which you've already written.
Node mergePass(Node list, int i)
:
merge
, and "pasting" the result in; then doing the same for nodes #(2n+1) to #(3n) and nodes #(3n+1) to #(4n); etc.Node mergeSort(Node list)
:
mergePass(..., 1)
on its argument.mergePass(..., 2)
on the result, then calls mergePass(..., 4)
on that result, etc., doubling i
each time.i
is the length of the list (or bigger), since mergePass(..., i)
is a no-op if i
is that big.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With