返回顶部

23. 合并K个排序链表

23. 合并K个排序链表

Difficulty: 困难

合并 _k _个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

Solution 1 二路归并

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int size = lists.size();
        if(size == 0) return nullptr;
        if(size == 1) return lists[0];
        for(int i = 0;i < size - 1;++i) {
            lists[i+1] = merge(lists[i],lists[i+1]);
        }
        return lists[size - 1]; 
    }
private:
    ListNode* merge(ListNode* headA,ListNode* headB) {
        if(headA == nullptr) return headB;
        if(headB == nullptr) return headA;
        ListNode *head = new ListNode(0),*temp = head;
        while(headA != nullptr && headB != nullptr) {
            if(headA->val < headB->val) {
                temp->next = headA;
                temp = temp->next;
                headA = headA->next;
            } else {
                temp->next = headB;
                temp = temp->next;
                headB = headB->next;
            }
        }
        temp->next = headA == nullptr ? headB : headA;
        head = head ->next;
        return head;
    }
};

思路

俩俩归并,两个数组归并一次得到长度为2n的数组,该数组继续与后面数组进行合并,分别得到3n、4n...kn长度的数组,而每一步所花时间都与长度成正比,故O(k2n)。使用了额外的空间为O(1)。


solution 2 分治合并

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return merge(lists,0,lists.size() - 1);    
    }

private:
    ListNode* merge(vector<ListNode*>& lists,int begin,int end) {
        if(begin == end ) return lists[begin];
        if(begin  > end) return nullptr;
        int mid = (begin + end) >> 1;
        return merge2Lists(merge(lists,begin,mid),merge(lists,mid + 1,end));
    }
    ListNode* merge2Lists(ListNode* headA,ListNode* headB) {
        if(headA == nullptr) return headB;
        if(headB == nullptr) return headA;
        ListNode *head = new ListNode(0),*temp = head;
        while(headA != nullptr && headB != nullptr) {
            if(headA->val < headB->val) {
                temp->next = headA;
                temp = temp->next;
                headA = headA->next;
            } else {
                temp->next = headB;
                temp = temp->next;
                headB = headB->next;
            }
        }
        temp->next = headA == nullptr ? headB : headA;
        head = head ->next;
        return head;
    }
};

思路

记一共有k个数组,每组长度都为n,则第一次合并,共合并\(\frac{k}{2}\)个数组,共耗时为O(\(kn\)),第二次合并共合并\(\frac{k}{4}\)个数组,共耗时为O(\(kn\)),依此类推,最后一次合并2个数组,共耗时O(\(kn\)),很容易得到树的高度为\(\log{k}\),每组耗时都是O(\(kn\)),所以总的时间复杂度O(\(kn\log{k}\)),空间复杂度O(\(\log{k}\))。

posted @ 2020-07-30 19:28  Swetchine  阅读(117)  评论(0)    收藏  举报