输入:一个链表数组 lists,其中每个链表都已经按升序排列。
要求:请你将所有链表合并为一个升序链表,并返回合并后的链表头结点。
输出:合并后的升序链表头结点。
思路1:暴力排序法(收集 + 排序 + 尾插法)
-
遍历所有链表节点,把所有数值放入一个数组
vals; -
对
vals进行排序; -
使用尾插法重新构建一个新的升序链表;
-
返回新链表的头结点。
复杂度:
-
时间复杂度:O(N log N)
-
空间复杂度:O(N)
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<int> vals;
// 1. 收集所有节点的值
for (auto head : lists) {
while (head) {
vals.push_back(head->val);
head = head->next;
}
}
// 2. 排序
sort(vals.begin(), vals.end());
// 3. 尾插法建表
ListNode dummy(0);
ListNode* tail = &dummy;
for (int v : vals) {
tail->next = new ListNode(v);
tail = tail->next;
}
return dummy.next;
}
};
思路2:优先队列法
利用priority_queue,实现一个自动选择当前最小节点的过程:
-
将所有链表的头节点放入小顶堆;
-
每次取出堆顶最小节点,接到新链表尾部;
-
若该节点有
next,则将next入堆; -
重复直到堆为空。
复杂度:
-
时间复杂度:O(N log K)
-
空间复杂度:O(K)
class Solution {
public:
struct Compare {
bool operator()(ListNode* a, ListNode* b) {
return a->val > b->val; // 小顶堆
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, Compare> pq;
// 1. 所有头节点入堆
for (auto node : lists) {
if (node) pq.push(node);
}
// 2. 虚拟头节点 + 尾插法
ListNode dummy(0);
ListNode* tail = &dummy;
while (!pq.empty()) {
ListNode* smallest = pq.top();
pq.pop();
tail->next = smallest;
tail = tail->next;
if (smallest->next) pq.push(smallest->next);
}
return dummy.next;
}
};
思路3:分治归并法(递归两两合并)
采用分治思想,将 K 个链表不断二分为左右两部分,递归合并:
-
若只有一个链表则直接返回;
-
否则递归合并左右两半;
-
最后再调用 LC.21 的“合并两个有序链表”来完成一次归并。
相当于对链表数组执行归并排序,每层合并 O(N),共有 logK 层。
复杂度:
-
时间复杂度:O(N log K)
-
空间复杂度:O(log K)
class Solution {
public:
// 合并两个有序链表(复用 LC.21 思路)
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode dummy(-1);
ListNode* tail = &dummy;
while (l1 && l2) {
if (l1->val <= l2->val) {
tail->next = l1;
l1 = l1->next;
} else {
tail->next = l2;
l2 = l2->next;
}
tail = tail->next;
}
tail->next = l1 ? l1 : l2;
return dummy.next;
}
// 分治递归合并
ListNode* merge(vector<ListNode*>& lists, int left, int right) {
if (left > right) return nullptr;
if (left == right) return lists[left];
int mid = (left + right) / 2;
ListNode* l1 = merge(lists, left, mid);
ListNode* l2 = merge(lists, mid + 1, right);
return mergeTwoLists(l1, l2);
}
// 主函数
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.empty()) return nullptr;
return merge(lists, 0, lists.size() - 1);
}
};
2523

被折叠的 条评论
为什么被折叠?



