leetcode : Merge K sorted Lists

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

题目的重点在与分析描述复杂度。。。一看到多路归并就想到外部排序结果果断二了个逼。

两种思路,一种是建个胜者树或者败者树进行k路归并。那么平均每得到一个最小值,需要进行logk次比较,一共k*n个元素,

复杂度为logk * n * k,即O(n)

其实建一个小根堆也可以,但是堆每次得到一个最小的元素,需要进行一次删除,一次插入,比败者树慢

 

第二种是建一个平衡二叉树,每个叶子节点为一个list,慢慢向上归并

每一层的归并复杂度为k*n,一共logk层,所以总的复杂度为k *logk *n,还是O(n)

所以非常逗比的两种思路的复杂度是一样的!!!

更进一步的,每次将一个新的段与第一段归并,那么复杂度为

2n + 3n + ..  k*n = O(k^2 *n)。还是O(n)。。。。

简单说来就是怎么都要O(n)..

再下面是外部排序,真是不知道哪个逗比在写外部排序的时候,说k路归并,每次找一个最小的需要k-1次比较,所以用败者树优化,

使得只要比较logk次。导致惯性的以为上面的思路1比思路2要快。

实际上对于外部排序思路1确实比思路2快,因为相比思路2,建立一个败者树大大减少了读取外存的次数--每个input文件都只要读一次,而最终的output文件也只要写一次。

AC代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        if(lists.size() == 0) return nullptr;
        return doMerge(lists, 0, lists.size() - 1);
    }
    ListNode *doMerge(vector<ListNode *> &lists, int start, int end){  
        if(start + 1 == end)
            return mergeTwoLists(lists[start], lists[end]);
        else if(start == end)
            return lists[start];
        else{
            auto l1 = doMerge(lists, start, (start + end) / 2);
            auto l2 = doMerge(lists, (start + end) / 2 + 1, end);
            return mergeTwoLists(l1, l2);
        }
    }
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2){  
        ListNode *head = nullptr, *tail = nullptr;
        while(l1 && l2){
            if(l1->val < l2->val){
                if(head){
                    tail->next = l1;
                }else{
                    head = l1;
                }
                tail = l1;
                l1 = l1->next;
            }else{
                if(head){
                    tail->next = l2;
                }else{
                    head = l2;
                }
                tail = l2;
                l2 = l2->next;
            }
        }
        auto temp = l1 ? l1 : l2;
        if(head)
            tail->next = temp;
        else
            head = temp;
        return head;
    }
};

 

posted on 2014-12-14 22:35  远近闻名的学渣  阅读(295)  评论(0)    收藏  举报

导航