Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
I have two ideas for this problem. One is divide and conquer, merge every two linked lists recursively. The other one is use a heap to store head nodes of each linked list, and each node pop the smallest one and push its successor into the current heap until there is nothing in the heap. I implemented the first approach in C++ and the second one in Python.
C++ Code:
/* * func: merge_two_lists * goal: merge 2 linked lists into one linked list * @param list1: linked list 1 * @param list2: linked list 2 * return: the new linked list * complexity: time O(n), space O(1) */ ListNode* merge_two_lists(ListNode* list1, ListNode* list2){ ListNode* iter1 = list1; ListNode* iter2 = list2; ListNode* result_head = nullptr; ListNode* result_iter = new ListNode(0); //Merge two lists while(iter1 != nullptr && iter2 != nullptr){ if(iter1->val <= iter2->val){ result_iter->next = iter1; iter1 = iter1->next; }else{ result_iter->next = iter2; iter2 = iter2->next; } //Get the head of new list if(result_head == nullptr){ result_head = result_iter->next; } result_iter = result_iter->next; } //Concatenate remaining of list1 while(iter1 != nullptr){ result_iter->next = iter1; iter1 = iter1->next; if(result_head == nullptr){ result_head = result_iter->next; } result_iter = result_iter->next; } //Concatenate remaining of list1 while(iter2 != nullptr){ result_iter->next = iter2; iter2 = iter2->next; if(result_head == nullptr){ result_head = result_iter->next; } result_iter = result_iter->next; } return result_head; } /* * func: merge_k_lists_helper * goal: recursive function to help merge lists * @param lists: vector of head node * @param begin: index of list 1 * @param end: index of list 2 * return: merged list */ ListNode* merge_k_lists_helper(vector<ListNode*> lists, int begin, int end){ if(begin > end){ return nullptr; } if(begin == end){ return lists.at(begin); } if(begin + 1 == end){ return merge_two_lists(lists.at(begin), lists.at(end)); } int mid = begin + (end-begin)/2; ListNode* left = merge_k_lists_helper(lists, begin, mid); ListNode* right = merge_k_lists_helper(lists, mid+1, end); return merge_two_lists(left, right); } /* * func: merge_k_lists * goal: merge k linked list into one linked list * @param lists: vector of head node * return: the new linked list */ /* * divide and conquer * complexity: time O(nlogk), space O(1) */ ListNode* merge_k_lists(vector<ListNode*> lists){ return merge_k_lists_helper(lists, 0, lists.size()-1); }
Python Code:
# func: merge k linked list into one list # @param lists: lists of head nodes # @return: head node of merged list def merge_k_lists(lists): if not lists: return None if len(lists) == 1: return lists[0] head = None curr_node = None heap = [] for node in lists: if node is not None: heapq.heappush(heap, (node.val, node)) #Use heap to construct while heap: value, min_node = heapq.heappop(heap) if head is None: head = min_node if curr_node is None: curr_node = min_node else: curr_node.next = min_node curr_node = curr_node.next min_node = min_node.next if min_node is not None: heapq.heappush(heap, (min_node.val, min_node)) return head
No comments:
Post a Comment