0x01.问题
合并 k 个排序链表,返回合并后的排序链表。
输入示例:
[
1->4->5,
1->3->4,
2->6
]
输出示例:
1->1->2->3->4->4->5->6
本题是上题的升级版 合并两个有序链表
C++结构体:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
C++函数形式: ListNode* mergeKLists(vector<ListNode*>& lists)
0x02.简要分析
与上个问题不同的是,这次要求的是k
个链表的排序,而不仅仅是两个链表的排序了。
但基本的思路还是不变的,还是从每个里面拿出一个最小值,加在结果链表上。
但考虑到这里链表由很多,所以暴力的取出肯定是不可取的。
有一个思路是将多个链表最终转换为两个链表的合并,这其实就是分治的思路,肯定是可以的,在这里,我们使用一种更加好理解的解决办法。
最暴力的思路应该就是将所有的链表都转换为数组,目的是什么,就是为了排序简单,那么,我们可不可以在遍历的时候做到排序了,也就是说放入一个有序的容器内,没错,优先队列 就可以做到,我们可以维护一个小顶堆,也就是最小值优先队列,先把头节点入优先队列,每次拿出的时候,再把它的下一个节点入优先队列,因为优先队列的优先级的关系,所以放入的数据会变成有序的,这样,我们每次只要从队头拿出一个元素放入结果链表中就行了。
借助优先队列的帮助,这个问题就变得非常简单了,只要不断得入队出队,就完成了这个排序得过程。
0x03.解决代码–优先队列
class Solution {
public:
struct mycomp{
bool operator()(ListNode* a,ListNode* b){
return a->val>b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, mycomp> queue;
for(ListNode*head:lists){
if(head) queue.push(head);
}
ListNode* dummy = new ListNode(-1);
ListNode* temp = dummy;
while(!queue.empty()){
ListNode* p = queue.top();
queue.pop();
if(p->next) queue.push(p->next);
temp->next=p;
temp=temp->next;
}
return dummy->next;
}
};
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null || lists.length==0) {
return null;
}
//创建一个堆,并设置元素的排序方式
PriorityQueue<ListNode> queue = new PriorityQueue(new Comparator<ListNode>() {
public int compare(ListNode o1, ListNode o2) {
return (o1.val - o2.val);
}
});
//遍历链表数组,然后将每个链表的每个节点都放入堆中
for(int i=0;i<lists.length;i++) {
while(lists[i] != null) {
queue.add(lists[i]);
lists[i] = lists[i].next;
}
}
ListNode dummy = new ListNode(-1);
ListNode head = dummy;
//从堆中不断取出元素,并将取出的元素串联起来
while( !queue.isEmpty() ) {
dummy.next = queue.poll();
dummy = dummy.next;
}
dummy.next = null;
return head.next;
}
}
ATFWUS --Writing By 2020–03–23