Merge k Sorted Lists leetcode
来源:互联网 发布:工厂巡检数据怎么分析 编辑:程序博客网 时间:2024/06/08 08:20
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
这道题目在分布式系统中非常常见,来自不同client的sorted list要在central server上面merge起来。这个题目一般有两种做法,下面一一介绍并且分析复杂度。 第一种做法比较容易想到,就是有点类似于MergeSort的思路,就是分治法,不了解MergeSort的朋友,请参见归并排序-维基百科,是一个比较经典的O(nlogn)的排序算法,还是比较重要的。思路是先分成两个子任务,然后递归求子任务,最后回溯回来。这个题目也是这样,先把k个list分成两半,然后继续划分,知道剩下两个list就合并起来,合并时会用到Merge Two Sorted Lists这道题,
算法1:leetcode超时
最傻的做法就是先1、2合并,12结果和3合并,123结果和4合并,…,123..k-1结果和k合并,我们计算一下复杂度。
1、2合并,遍历2n个节点
12结果和3合并,遍历3n个节点
123结果和4合并,遍历4n个节点
…
123..k-1结果和k合并,遍历kn个节点
总共遍历的节点数目为n(2+3+…+k) = n*(k^2+k-2)/2, 因此时间复杂度是O(n*(k^2+k-2)/2) = O(nk^2),代码如下:
class Solution {public: ListNode *mergeKLists(vector<ListNode *> &lists) { if(lists.size() == 0) return nullptr; ListNode* res = lists[0]; for(int i=1;i<lists.size();i++) { res = mergeLists(res,lists[i]); } return res; } ListNode* mergeLists(ListNode* a,ListNode* b) { if(a == nullptr) return b; if(b == nullptr) return a; ListNode* helper = new ListNode(0); ListNode* pNodeA = a; ListNode* pNodeB = b; ListNode* last = helper; while(pNodeA != nullptr && pNodeB != nullptr) { if(pNodeA->val <= pNodeB->val) { last->next = pNodeA; pNodeA = pNodeA->next; } else { last->next = pNodeB; pNodeB = pNodeB->next; } last = last->next; } if(pNodeA != nullptr) last->next = pNodeA; if(pNodeB != nullptr) last->next = pNodeB; return helper->next; }};算法2:利用分治的思想把合并k个链表分成两个合并k/2个链表的任务,一直划分,知道任务中只剩一个链表或者两个链表。可以很简单的用递归来实现。因此算法复杂度为T(k) = 2T(k/2) + O(nk),很简单可以推导得到算法复杂度为O(nklogk)
ListNode *mergeKLists(vector<ListNode *> &lists) { if(lists.size() == 0) return nullptr; return helper(lists,0,lists.size()-1); } ListNode* helper(vector<ListNode *> &lists,int l,int r) { if(l<r) { int m = l + (r-l)/2; return mergeLists(helper(lists,l,m),helper(lists,m+1,r)); } return lists[l]; }
下面是非递归的代码非递归的思想是(以四个链表为例):
1、3合并,合并结果放到1的位置
2、4合并,合并结果放到2的位置
再把1、2合并(相当于原来的13 和 24合并)
ListNode *mergeKLists(vector<ListNode *> &lists) { int n = lists.size(); if(n == 0)return NULL; while(n >1) { int k = (n+1)/2; for(int i = 0; i < n/2; i++) lists[i] = merge2list(lists[i], lists[i + k]); n = k; } return lists[0]; }
算法3:维护一个k个大小的最小堆,初始化堆中元素为每个链表的头结点,每次从堆中选择最小的元素加入到结果链表,再选择该最小元素所在链表的下一个节点加入到堆中。这样当堆为空时,所有链表的节点都已经加入了结果链表。元素加入堆中的复杂度为O(longk),总共有kn个元素加入堆中,因此,复杂度也和算法2一样是O(nklogk)
class Solution {private:struct cmp{ bool operator ()(const ListNode *a, const ListNode *b) { return a->val > b->val; }};public: ListNode *mergeKLists(vector<ListNode *> &lists) { int n = lists.size(); if(n == 0)return NULL; ListNode node(0), *res = &node; priority_queue<ListNode*, vector<ListNode*>, cmp> que; for(int i = 0; i < n; i++) if(lists[i]) que.push(lists[i]); while(!que.empty()) { ListNode * p = que.top(); que.pop(); res->next = p; res = p; if(p->next) que.push(p->next); } return node.next; }};
- LeetCode: Merge k Sorted Lists
- LeetCode Merge k Sorted Lists
- LeetCode: Merge k Sorted Lists
- [Leetcode] Merge k Sorted Lists
- [Leetcode] Merge k Sorted Lists
- [Leetcode] Merge K sorted lists
- [LeetCode]Merge k Sorted Lists
- [LeetCode] Merge k Sorted Lists
- LeetCode-Merge k Sorted Lists
- LeetCode: Merge k Sorted Lists
- LeetCode - Merge k Sorted Lists
- LeetCode | Merge k Sorted Lists
- 【leetcode】Merge k Sorted Lists
- Leetcode: Merge k Sorted Lists
- <Leetcode>Merge k Sorted Lists
- [LeetCode] Merge K sorted lists
- [LeetCode] Merge k Sorted Lists
- 【Leetcode】Merge k Sorted Lists
- VC编程环境下灵活运用
- jquery ajax error用法
- coco2d-x 3.x 实现帧动画
- C和指针----->第二章(基本概念)->C执行文件的产生和代码规范
- openerp 生产模块管理
- Merge k Sorted Lists leetcode
- VC++程序员如何做好界面
- cocos2d-x-3.x guides
- 读《反欺骗的艺术》有感
- 开发者应该多一点软件工程思想
- <数据结构> 顺序表算法描述之N-S图
- 杭电acm2021发工资咯:)
- 解决MyEclipse下Tomcat启动变慢的方法
- 2014092201