目录
23.合并k个排序链表 H
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
方法 1:暴力
想法 & 算法
- 遍历所有链表,将所有节点的值放到一个数组中。
- 将这个数组排序,然后遍历所有元素得到正确顺序的值。
- 用遍历得到的值,创建一个新的有序链表。
方法 2:逐一比较
算法
- 比较 k 个节点(每个链表的首节点),获得最小值的节点。
- 将选中的节点接在最终有序链表的后面。
复杂度分析
-
时间复杂度: O(kN), 其中 k 是链表的数目。
- 几乎最终有序链表中每个节点的时间开销都为 O(k) (k-1 次比较)。
- 总共有 N 个节点在最后的链表中。
-
空间复杂度:
- O(n) 。创建一个新的链表空间开销为 O(n)O(n) 。
- O(1) 。重复利用原来的链表节点,每次选择节点时将它直接接在最后返回的链表后面,而不是创建一个新的节点。
方法 3:用优先队列优化方法 2
算法
几乎与上述方法一样,除了将 比较环节 用 优先队列 进行了优化。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
struct cmp{ //对新的数据类型的<进行重写
bool operator()(ListNode *a,ListNode *b){
return a->val > b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode* ,vector<ListNode*> , cmp> heapk;
for(auto p:lists){
if(p!=NULL){
heapk.push(p);
}
}
ListNode *pHead = new ListNode(-1);
ListNode *pCur = pHead;
while(!heapk.empty()){
ListNode *top = heapk.top();heapk.pop();
pCur->next = top;
pCur = pCur->next;
if(top->next!=NULL){
heapk.push(top->next);
}
}
pCur = pHead->next;
delete pHead;
return pCur;
}
};
方法 5:分治
想法 & 算法
- 将 k 个链表配对并将同一对中的链表合并。
- 第一轮合并以后, k 个链表被合并成了 k/2 个链表,平均长度为 2N/k ,然后是k/4 个链表,k/8 个链表等等。
- 重复这一过程,直到我们得到了最终的有序链表。
因此,我们在每一次配对合并的过程中都会遍历几乎全部 N 个节点,并重复这一过程 log2K 次。
类似归并排序的回溯过程,两两合并。 O(Nlog2K)
public class Test {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val - o2.val;
}
});
for(ListNode e : lists) {
if(e!=null)
pq.add(e);
}
ListNode head = new ListNode(0);
head.next = null;
ListNode tail = head;
while(!pq.isEmpty()) {
tail.next = pq.poll();
tail = tail.next;
if(tail.next!=null) {
pq.add(tail.next);
}
tail.next = null;
}
return head.next;
}
}
215. 数组中的第K个最大元素
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int,vector<int>,greater<int>> q;
for(auto it:nums){
q.push(it);
if(q.size()>k) q.pop();
}
return q.top();
}
};