[leetcode] 23. Merge k Sorted Lists 解题报告

来源:互联网 发布:文件管理器源码 编辑:程序博客网 时间:2024/05/18 00:58

题目链接:https://leetcode.com/problems/merge-k-sorted-lists/

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


思路:刚开始想要两两合并,但是超时了,后来看到用优先队列来做会降低很多时间复杂度。我看到很多人分析时间复杂度有很多错误,那么我们先来分析一下这两种做法的时间复杂度。

首先是两两合并,这种方法的思路比较简单,两个合并之后再和后来的合并,其时间复杂度分析如下,第一个列是行号,第二列是一个链表的元素个数,第三列是合并用的时间:

1    n    0

2    n    n+n

3    n    2*n+n   //因为此时前面链表合并过之后的长度变为2*n

4    n    3*n+n   //前面合并的链表长度变为3*n

5    n    4*n+n

.....

k    n    (k-1)*n+n

因此可以得出总的运行时间为:

 2*n+3*n+4*n+...+k*n 

= n * ( k * (k+1)/2 - 1 ) 

= n*(k * k/2 + k * 2 - 1) 

= n*k*k/2 + n*k*2 - n

因此可以得出两两合并时间复杂度为O(n*k*k)。


 然后再来分析一下用优先队列的思路和时间复杂度。

这种方式的思路是将k个链表放到小顶堆组成的优先队列中。每次取出顶部元素,时间复杂度是O(1),取出顶部元素之后再将其后的元素插入到堆中。

这样最终就可以将所有元素取出。时间复杂分析如下:

总共会有n*k个元素,每个元素都会插入和删除到优先队列中,因为优先队列的长度是k,即链表的个数,因此插入删除时间复杂度都是O(log(k)),这样总的时间复杂度将为O(n*k*log(k)).

优先队列代码如下:

/** * 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) {        auto cmp = [](ListNode* a, ListNode* b) { return a->val > b->val; };        priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> que(cmp);        ListNode *pHead = new ListNode(0), *p = pHead;        for(auto val: lists) if(val) que.push(val);        while(!que.empty())        {            auto val = que.top();            p->next = val, p = p->next;            que.pop();            if(val->next) que.push(val->next);        }        p = pHead->next;        delete pHead;        return p;    }};
参考:http://bangbingsyb.blogspot.com/2014/11/leetcode-merge-k-sorted-lists.html



0 0
原创粉丝点击