博文中会简要介绍Leetcode P0023题目分析及解题思路。
“Merge k Sorted Lists”是一道原型题,使用优先级队列(堆)来解决。p0021是其简化版。
Given an array of linked-lists lists, each linked list is sorted in ascending order.
Merge all the linked-lists into one sort linked-list and return it.
这道题的思路比较直接,时间复杂度是O(nlogk)。通过使用堆算法和数据结构,不断获取当前k个链表中的具有最小值的结点,然后将其连在新链表末尾,并且将其指针向后移动一格,将指针新指向的结点加入堆中,此时根据堆的特性,堆会进行上移或者下移来保证堆顶(也就是队列头)始终是当前堆中的具有最小值的结点。
下一个循环继续拿出堆顶元素,重复上述操作,直到堆为空。
以下是Java的题解代码实现。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0)
return null;
Queue<ListNode> pQueue = new PriorityQueue<>(new Comparator<>() {
@Override
public int compare(ListNode l1, ListNode l2) {
return l1.val-l2.val;
}
});
ListNode dummy = new ListNode(0, null);
ListNode tail = dummy;
for (ListNode node: lists) {
if (node != null)
pQueue.offer(node);
}
while (!pQueue.isEmpty()) {
ListNode itr = pQueue.poll();
if (itr.next != null)
pQueue.offer(itr.next);
tail.next = itr;
tail = tail.next;
}
return dummy.next;
}
}
关于C++中的优先级队列写法,主要有如下三种:
首先,priority_queue的模板是:
priority_queue<Type, Container, Typename> pq([lambda], [container]);
1. 写仿函数传入Typename:
struct Comparator {
bool operator() (x, y) {...}
};
2. 直接在对应Type的类中重载operator<。必须写成友元函数或者常量成员函数
3. 写成lambda表达式:
auto comparator = [](x, y) -> bool {...};
在Typename传入decltype(comparator),并在[lambda]参数上传入comparator,即传入写好的lambda
以下是C++的题解代码实现。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
struct NodeComparator {
bool operator() (ListNode *l1, ListNode *l2) {
return l1->val > l2->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.size() == 0)
return NULL;
// Lambda
// auto node_comp = [](ListNode *l1, ListNode *l2) -> bool {
// return l1->val > l2->val;
// };
// priority_queue<ListNode*, vector<ListNode*>, decltype(node_comp)> heap(node_comp);
// 仿函数
priority_queue<ListNode*, vector<ListNode*>, NodeComparator> heap;
ListNode *dummy = new ListNode(0);
ListNode *tail = dummy;
for (ListNode *node: lists) {
if (node != NULL)
heap.push(node);
}
while (!heap.empty()) {
ListNode *temp = heap.top();
heap.pop();
if (temp->next != NULL)
heap.push(temp->next);
tail->next = temp;
tail = tail->next;
}
return dummy->next;
}
};