zoukankan      html  css  js  c++  java
  • [LeetCode] 23. Merge k Sorted Lists 合并k个有序链表

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

    Example:

    Input:
    [
      1->4->5,
      1->3->4,
      2->6
    ]
    Output: 1->1->2->3->4->4->5->6

    21. Merge Two Sorted Lists的拓展,这道题要合并k个有序链表。

    解法1: 两两合并。1和2合并,结果在和3合并,以此类推,直到结束。时间复杂度为:2n + 3n + ... + kn = [(k+1)*k/2-1]*n = O(nk^2),空间复杂度为O(1)

    解法2: 分治法Divide and Conquer,也就是二分法。每次将所有的list两两之间合并,直到所有list合并成一个。时间复杂度:2n * k/2 + 4n * k/4 + ... + (2^x)n * k/(2^x) = O(nklogk),如果用迭代空间复杂度为O(1),用递归则空间复杂度为O(logk)。

    解法3: 最小堆MinHeap/priority queue,取每个Linked List的最小节点放入一个heap中,排序成最小堆,取出堆顶最小的元素,放入合并的list中,然后将该节点在其list中的下一个节点插入heap,循环上面步骤,以此类推直到全部节点都经过heap。由于heap的大小为始终为k,而每次插入的复杂度是logk,一共插入了nk个节点。时间复杂度为O(nklogk),空间复杂度为O(k)。

    Python: Merge two by two, Time: O(nk^2), Space: O(1)

    class Solution(object):
        def mergeKLists(self, lists):
            def mergeTwoLists(l1, l2):
                curr = dummy = ListNode(0)
                while l1 and l2:
                    if l1.val < l2.val:
                        curr.next = l1
                        l1 = l1.next
                    else:
                        curr.next = l2
                        l2 = l2.next
                    curr = curr.next
                curr.next = l1 or l2
                return dummy.next
    
            if not lists:
                return None
            left, right = 0, len(lists) - 1;
            while right > 0:
                if left >= right:
                    left = 0
                else:
                    lists[left] = mergeTwoLists(lists[left], lists[right])
                    left += 1
                    right -= 1
            return lists[0]
    

    Python: Divide and conquer, Time: O(nklogk), Space: O(logk)

    class Solution:
        def mergeKLists(self, lists):
            def mergeTwoLists(l1, l2):
                curr = dummy = ListNode(0)
                while l1 and l2:
                    if l1.val < l2.val:
                        curr.next = l1
                        l1 = l1.next
                    else:
                        curr.next = l2
                        l2 = l2.next
                    curr = curr.next
                curr.next = l1 or l2
                return dummy.next
        
            def mergeKListsHelper(lists, begin, end):
                if begin > end:
                    return None
                if begin == end:
                    return lists[begin]
                return mergeTwoLists(mergeKListsHelper(lists, begin, (begin + end) / 2), 
                                     mergeKListsHelper(lists, (begin + end) / 2 + 1, end))
       
            return mergeKListsHelper(lists, 0, len(lists) - 1)
    

    Python: Heap, Time: O(nklogk), Space: O(k)

    import heapq
    class Solution:
        def mergeKLists(self, lists):
            dummy = ListNode(0)
            current = dummy
            
            heap = []
            for sorted_list in lists:
                if sorted_list:
                    heapq.heappush(heap, (sorted_list.val, sorted_list))
                    
            while heap:
                smallest = heapq.heappop(heap)[1]
                current.next = smallest
                current = current.next
                if smallest.next:
                    heapq.heappush(heap, (smallest.next.val, smallest.next))
                    
            return dummy.next  

    C++: Merge two by two

    class Solution {
    public:
        ListNode *mergeKLists(vector<ListNode *> &lists) {
            ListNode *ret = NULL;
            for(int i=0; i<lists.size(); i++) 
                ret = merge2Lists(ret, lists[i]);
            return ret;
        }
        
        ListNode* merge2Lists(ListNode *h1, ListNode *h2) {
            ListNode *dummy = new ListNode(0), *tail = dummy;
            while(h1 && h2) {
                if(h1->val<=h2->val) {
                    tail->next = h1;
                    h1 = h1->next;
                }
                else {
                    tail->next = h2;
                    h2 = h2->next;
                }
                tail = tail->next;
            }
            tail->next = h1 ? h1 : h2;
            return dummy->next;
        }
    };
    

    C++: Divide and Conque

    class Solution {
    public:
        ListNode *mergeKLists(vector<ListNode *> &lists) {
            if(lists.empty()) return NULL;
            int end = lists.size()-1;
            while(end>0) {
                int begin = 0;
                while(begin<end) {
                    lists[begin] = merge2Lists(lists[begin], lists[end]);
                    begin++;
                    end--;
                }
            }
            return lists[0];
        }
        
        ListNode* merge2Lists(ListNode *h1, ListNode *h2) {
            ListNode *dummy = new ListNode(0), *tail = dummy;
            while(h1 && h2) {
                if(h1->val<=h2->val) {
                    tail->next = h1;
                    h1 = h1->next;
                }
                else {
                    tail->next = h2;
                    h2 = h2->next;
                }
                tail = tail->next;
            }
            tail->next = h1 ? h1 : h2;
            return dummy->next;
        }
    };
    

    C++: priority queque

    class Solution {
    public:
        struct compNode {
            bool operator()(ListNode *p, ListNode *q) const {
                return p->val>q->val;
            }  
        };
    
        ListNode *mergeKLists(vector<ListNode *> &lists) {
            priority_queue<ListNode*, vector<ListNode*>, compNode> pq;
            ListNode *dummy = new ListNode(0), *tail = dummy;
            
            for(int i=0; i<lists.size(); i++) 
                if(lists[i]) pq.push(lists[i]);
                
            while(!pq.empty()) {
                tail->next = pq.top();
                tail = tail->next;
                pq.pop();
                if(tail->next) pq.push(tail->next);
            }
            
            return dummy->next;
        }
    };  

       

    类似题目:

    [LeetCode] 21. Merge Two Sorted Lists 合并有序链表

    [LeetCode] 88. Merge Sorted Array 合并有序数组

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    linq 读取xml
    c# 定时器 自动执行
    如何在一个人输入框中只输入数字
    如何去掉滚动条,
    如何计算任意值之间的随机数呢
    【P2387】魔法森林(SPFA非正解)
    【Luogu】P3203弹飞绵羊(分块)
    【Luogu】P3396哈希冲突(根号算法)
    【Luogu】P2801教主的魔法(分块)
    【Luogu】P3155叶子的染色(树形DP)
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8512912.html
Copyright © 2011-2022 走看看