23. 合并K个升序链表
题目描述
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例2:
输入:lists = []
输出:[]
示例3:
输入:lists = [[]]
输出:[]
提示:
- k = = l i s t s . l e n g t h k == lists.length k==lists.length
- 0 ≤ k ≤ 1 0 4 0 \le k \le 10^4 0≤k≤104
- 0 ≤ l i s t s [ i ] . l e n g t h ≤ 500 0 \le lists[i].length \le 500 0≤lists[i].length≤500
- − 1 0 4 ≤ l i s t s [ i ] [ j ] ≤ 1 0 4 -10^4 \le lists[i][j] \le 10^4 −104≤lists[i][j]≤104
- lists[i] 按 升序 排列
- lists[i].length 的总和不超过 1 0 4 10^4 104
题解:
法一:
顺序合并,从前往后逐个合并每个链表。
时间复杂度: O ( k 2 ∗ n ) O(k^2 * n) O(k2∗n)
额外空间复杂度: O ( 1 ) O(1) O(1)
法一代码:
/**
* 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:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if ( !lists.size() ) return nullptr;
ListNode dummy;
ListNode *l1 = nullptr, *l2 = nullptr, *pre = nullptr;
for ( auto& it : lists ) {
if ( !it ) continue;
pre = &dummy;
l1 = dummy.next;
l2 = it;
while ( l1 && l2 ) {
if ( l1->val <= l2->val ) {
pre->next = l1;
l1 = l1->next;
} else {
pre->next = l2;
l2 = l2->next;
}
pre = pre->next;
}
pre->next = l1 ? l1 : l2;
}
return dummy.next;
}
};
/*
时间:164ms,击败:30.20%
内存:12.7MB,击败:99.67%
*/
法二:
使用分治法进行合并。
时间复杂度: O ( k ∗ n × l o g k ) O(k*n \times logk) O(k∗n×logk)
额外空间复杂度: O ( l o g k ) O(logk) O(logk)
法二代码:
/**
* 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:
ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
if ( !a || !b ) return a ? a : b;
ListNode dummy, *tail = &dummy;
while ( a && b ) {
if ( a->val <= b->val ) {
tail->next = a;
a = a->next;
} else {
tail->next = b;
b = b->next;
}
tail = tail->next;
}
tail->next = a ? a : b;
return dummy.next;
}
ListNode* merge(vector<ListNode*>& lists, int l, int r ) {
if ( l > r ) return nullptr;
if ( l >= r ) return lists[l];
int m = (l + r) >> 1;
return mergeTwoLists( merge(lists, l, m), merge(lists, m + 1, r) );
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if ( !lists.size() ) return nullptr;
return merge( lists, 0, lists.size() - 1);
}
};
/*
时间:24ms,击败:99.67%
内存:12.5MB,击败:99.96%
*/
法三:
构建一个大小为 K 的小根堆,维护每个链表未被合并的第一个节点,每次取出堆顶元素(值最小),然后将其下一个节点的值插入堆中。
时间复杂度: O ( k ∗ n × l o g k ) O(k*n \times logk) O(k∗n×logk)
额外空间复杂度: O ( k ) O(k) O(k)
/**
* 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 Node {
ListNode *ptr;
bool operator < ( const Node& rhs ) const {
return ptr->val > rhs.ptr->val;
}
};
priority_queue<Node> q;
ListNode* mergeKLists(vector<ListNode*>& lists) {
for( auto& it : lists ) {
if ( it ) q.push( {it} );
}
ListNode dummy, *tail = &dummy;
while ( q.size() ) {
auto t = q.top();
q.pop();
tail->next = t.ptr;
tail = tail->next;
if ( t.ptr->next ) q.push( {t.ptr->next} );
}
return dummy.next;
}
};
/*
时间:24ms,击败:99.67%
内存:12.9MB,击败:99.41%
*/
顺便贴个手写小根堆代码:
/**
* 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:
vector<ListNode*> heap;
int sze;
void down( int u ) {
int t = u;
if ( u * 2 + 1 < sze && heap[u * 2 + 1]->val < heap[t]->val ) t = u * 2 + 1;
if ( u * 2 + 2 < sze && heap[u * 2 + 2]->val < heap[t]->val ) t = u * 2 + 2;
if ( t == u ) return;
swap( heap[t], heap[u] );
down( t );
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if ( !lists.size() ) return nullptr;
for ( auto& it : lists ) {
if ( it ) heap.push_back( it );
}
sze = heap.size();
for ( int i = sze >> 1; i >= 0; --i ) down( i );
ListNode dummy, *tail = &dummy;
while ( sze ) {
auto t = heap[0];
tail->next = t;
tail = tail->next;
if ( t->next ) {
heap[0] = t->next;
} else {
heap[0] = heap[--sze];
}
down( 0 );
}
return dummy.next;
}
};
/*
时间:28ms,击败:98.47%
内存:12.8MB,击败:99.57%
*/