#23 Merge K Sorted Lists (N-Way merge sort)
Title Address: #23
Title Category: List/merge sort/heap sort
Problem Difficulty: Hard
Topic
Merge K sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Translation: Merges K-sorted lists and returns a sorted list.
Ideas
Violence law, it's easy to think: traverse all linked lists with a For loop, find the smallest, and add this node to the new list
- Complexity of Time: O (k*n)
- Reviews: Simple and rude, but the performance is too weak. Every time you go through all the linked lists, test results tle
Divide-and-conquer method + Merge: for K-linked list, using the idea of divide and conquer, each merge 2 until the end of a sorted list
- Complexity of Time: O (N*LGK)
- After careful analysis, the actual traversal should be exactly n*lg (k), because each layer of the merge will traverse all elements once, and there is a total of LG (k) Layer
- Reviews: Optional methods, for linked lists, do not need to introduce additional space. But what about arrays? That would require a lot of extra space!
Minimum heap : The reference Violence Law, for this k list, each time we do the operation is:
1-Find the smallest node nodes min;
2-Add node min to the new linked list
3-node min = Node min-Next
In the law of violence, our flaw is that we cannot effectively find the smallest element of the present. The For loop does a lot of repetitive comparisons, which is undoubtedly a waste
Therefore, we pre-build the node array nodes [] into the smallest heap, and then only need to remove the first element at a time.
- Time complexity: O (k) + O (n*lgk)
- Description of time complexity : Here, it takes O (k) time to construct the minimum heap, compared to the divide-and-conquer method, there are obviously:
O (k) + O (n*lgk) > O (nlgk)
This is the wrong way to think ... Thought 2 mentioned that the division of the merger in fact each time is exactly right:
n*lgk number of times to traverse elements +n*lgk times
In contrast, the minimum heap, in addition to the cost of the first build, is maintained on the heap. So this o (n*lgk) should be--
the maximum number of times each element is compared (worst case) + each element is traversed 1 times
therefore, the minimum heap in a large number of data cases, is definitely better than the division of the merger!
- Reviews: The minimum heap complex under construction + maintenance heap, but the performance improvement is great.
Better way to--loser Tree
Pending additions
Trap
For the problem, instead of examining the implementation of the algorithm, there is no small pits can jump.
Just pay attention to the handling of NULL pointers here.
My choice is to replace the null pointer with a node of value = Int_max
So this node will only be sunk to the bottom of the heap, do not need to waste comparison times
The termination condition is set to: The first element is this Int_max node
For this idea, think of some array aspects of the sorting problem of the boundary processing. * * If you are looking for a number in an array, the general practice is to
for (int i=0;i! =size;i++) {if (A[i]==flag) ...}
But this will need to compare size and I every time. You can do this: place a flag at the border, and once a[i] = = Flag, you can exit the loop.
above is a digression
Test case
- Enter NULL for the entire
- Linked list with NULL in input array
- Performance test, OJ's test case contains 10,000 linked lists
Code
C
voidMin_heap_sort (structListNode **lists,intIndex_i,intSize) {intleft = index_i*2+1;intright= index_i*2+2;if(left>=size)return;int min;if(right>=size)min= left;Else min= lists[left]->val<lists[right]->val?left:right;if(lists[index_i]->val>lists[min]->val) {structListNode *temp = lists[index_i]; Lists[index_i] = lists[min]; lists[min] = temp; Min_heap_sort (lists,min, size); }}voidBuildheap (structListNode **lists,intSize) { for(intI= (size-1)/2; i>=0;-i) {min_heap_sort (lists,i,size); }}structListNode *mergeklists (structListNode *lists[],intK) {if(k==0)returnNULL;//1 structListNode *head = (structlistnode*) malloc (sizeof (structListNode));structListNode *int_max = (structlistnode*) malloc (sizeof (structListNode)); Int_max->val = Int_max; Int_max->next = NULL;structListNode *travel = head; for(intI=0; i<k;++i) {if(lists[i]==null) lists[i] = Int_max; }/*remove those NULL ptr*/Buildheap (LISTS,K); while(lists[0]!=int_max) {Travel->next = lists[0]; Travel = lists[0]; lists[0] = lists[0]->next;if(lists[0]==null) lists[0] = Int_max; Min_heap_sort (lists,0, k); } travel->next = NULL;returnHead->next;}
Other solutions on the Leetcode
- Divide and conquer + merge: Divide-and-conquer
- Use the simple Java version of the Heap class: 13lines in Java
- Java priority queues: A Java solution based on priority queue
- Best of the year. Luxury low-key brute force solution: You are a genius ... Boy
#23 Merge K Sorted Lists (N-Way merge sort)