[LeetCode] Merge k Sorted Lists 解题报告
来源:互联网 发布:win10系统占用80端口 编辑:程序博客网 时间:2024/05/06 16:56
[题目]
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
[中文翻译]
合并k个已排好序的链表,并将其作为一个链表返回。 分析和描述其复杂性。
[解题思路]
这题的朴素思路可以先参考[LeetCode] Merge Two Sorted Lists 解题报告 。
之前merge的时候是找两个链表头的最小值,比较一下就很容易得到。现在是找k个链表头的最小值,遍历一遍,记下最小值在哪个链表,然后把那个链表头插入结果链表即可。一轮一轮地把最小的那个节点取出来,直到所有链表为空。
这种方法很朴素,假设每个链表都有d个元素,那么效率是O(k2d),因为一共有kd个节点,处理每个节点时都需要用k的时间复杂度选出最小的那个。
我们可以用最小堆的结构来更快地获得最小的节点,效率为O(logk),因此总的效率为O(kdlogk)。堆是一种数据结构,对于N个元素的堆,建堆、插入、删除、修改的时间效率均为O(logN),堆不支持查找。
堆一般为二叉堆,结构如图1。最小堆保证,父节点一定比它的子节点小。
图1 堆的结构
插入
例如我们需要插入元素34,先将它放在最后的位置,然后不断地与那它与父节点比较,如果比父节点小,就与父节点交换,直到无法继续向上交换。这样就能够在O(logN)的时间内插入一个元素,同时维护最小堆的性质。
图2 插入元素删除
例如我们需要删除元素2(由于最小堆的目的本身就是连续地获得最小值,所以一般我们都是删除堆顶元素)。我们采取的方法不是把下面的节点向上交换,而是用末尾的节点替换堆顶节点,然后把它不断往下沉。不断的与它子节点中最小的一个交换,直到无法继续下沉。
图3 删除元素修改
修改和删除一个道理,不断地拿当前元素往下沉。建堆
建堆有两种方法,最直接的方法就是在一个空堆中,不断的插入元素,效率为O(NlogN)。另一种方法是,先把乱序的元素放进堆里,然后去维护堆的性质,从后往前遍历节点,把当前节点当做刚修改过的元素不断地下沉,可以证明这种方法的效率为O(N)。
在这个问题里,堆的元素是链表。每次取出堆顶链表的表头,插入结果链表,然后更新堆顶链表,并维护堆。代码实现地比较烦,主要是因为维护的这个堆是一个链表,而不是数字,因此关于一个节点有没有子节点、有多少子节点,以及链表为NULL时,都需要做一些判断,不能像数字一样设一个MaxValue了事。
[C++代码]
Solution1,朴素地找最小值
class Solution {public: ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode dummy(0); ListNode* p = &dummy; int listNumber = lists.size(); int minIndex, minValue; while (true) { minIndex = listNumber; for (int i = 0; i < listNumber; i++) { if (lists.at(i) && (minIndex == listNumber || lists.at(i)->val < minValue)) { minIndex = i; minValue = lists.at(i)->val; } } if (minIndex == listNumber) break; p->next = lists.at(minIndex); lists.at(minIndex) = lists.at(minIndex)->next; p = p->next; } return dummy.next; }};
Solution2,用堆维护获得最小值
class Solution {public: ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode dummy(0); ListNode* p = &dummy; ListNode* tmp; int listsNumber = lists.size(); if (0 == listsNumber) return NULL; // 建堆,倒着遍历,可证明效率为O(n) for (int j = listsNumber - 1; j >= 0; j--) { int i = j; while (true) { int leftSon = 2 * i + 1; int rightSon = 2 * i + 2; int nextI = i; if (leftSon < listsNumber && lists.at(leftSon) && (!lists.at(nextI) || lists.at(leftSon)->val < lists.at(nextI)->val)) nextI = leftSon; if (rightSon < listsNumber && lists.at(rightSon) && (!lists.at(nextI) || lists.at(rightSon)->val < lists.at(nextI)->val)) nextI = rightSon; if (nextI == i) break; tmp = lists.at(nextI); lists.at(nextI) = lists.at(i); lists.at(i) = tmp; i = nextI; } } while (lists.at(0)) { p->next = lists.at(0); p = p->next; lists.at(0) = lists.at(0)->next; // 维护堆 int i = 0; while (true) { int leftSon = 2 * i + 1; int rightSon = 2 * i + 2; int nextI = i; if (leftSon < listsNumber && lists.at(leftSon) && (!lists.at(nextI) || lists.at(leftSon)->val < lists.at(nextI)->val)) nextI = leftSon; if (rightSon < listsNumber && lists.at(rightSon) && (!lists.at(nextI) || lists.at(rightSon)->val < lists.at(nextI)->val)) nextI = rightSon; if (nextI == i) break; tmp = lists.at(nextI); lists.at(nextI) = lists.at(i); lists.at(i) = tmp; i = nextI; } } return dummy.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] 23. Merge k Sorted Lists 解题报告
- [Leetcode] 23. Merge k Sorted Lists 解题报告
- Merge k Sorted Lists解题报告
- LeetCode解题报告--Merge Two Sorted Lists
- 【LeetCode】Merge Two Sorted Lists 解题报告
- [LeetCode] Merge Two Sorted Lists 解题报告
- Leetcode Merge Two Sorted Lists 解题报告
- Leetcode #23 Merge k Sorted Lists 合并K个有序列表 解题报告
- LeetCode 23:Merge k Sorted Lists 解题与思考
- leetcode解题方案--023--Merge k Sorted Lists
- [leetcode] 21. Merge Two Sorted Lists 解题报告
- [Leetcode] 21. Merge Two Sorted Lists 解题报告
- leetcode解题报告21. Merge Two Sorted Lists
- 初识Box Model
- linux下的LVM初识
- 莱迪思产品ICEstick Evaluation Kit 简介
- Gcc学习笔记
- java--10--多态
- [LeetCode] Merge k Sorted Lists 解题报告
- git命令收集(记得持续更新)
- 3.13
- USACO 2016 Feb Circular Barn 二分+树状数组
- 127.0.0.1和0.0.0.0地址的区别
- CSS三种样式
- Thymeleaf html代码使用nginx与java代码分离
- 计算机网络学习1:HTTP协议中URL和URI的区别
- 智能指针类和OpenCV的Ptr模板类