合併 k 條已排序的鏈表,返回合併後的有序鏈表。分析時間複雜度。
依次將當前結果與下一條鏈表合併,時間 O(k × N),其中 N 為總節點數。LeetCode 測試用例大時會 TLE。
// TLE 版本
ListNode* mergeKLists(vector<ListNode*> &lists) {
ListNode *head = nullptr;
for (auto list : lists) head = mergeTwoLists(head, list);
return head;
}
k 條鏈表的頭節點放入最小堆next,將 next 入堆堆中始終維護 k 個候選最小節點,每次操作 O(log k),總節點 N,總體 O(N log k)。
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
struct ListNode {
int val; ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*> &lists) {
ListNode dummy(-1);
ListNode *tail = &dummy;
// 自定義比較器:最小堆
struct Compare {
bool operator()(ListNode* a, ListNode* b) { return a->val > b->val; }
};
priority_queue<ListNode*, vector<ListNode*>, Compare> pq;
// 初始化:非空鏈表頭節點入堆
for (auto node : lists) if (node) pq.push(node);
while (!pq.empty()) {
ListNode *cur = pq.top(); pq.pop();
tail->next = cur;
tail = cur;
if (cur->next) pq.push(cur->next);
}
return dummy.next;
}
};
// 輔助:構建鏈表、輸出、主函數測試(略)
| 方法 | 時間 | 空間 | 備註 |
|---|---|---|---|
| 兩兩合併 | O(kN) | O(1) | k 大時退化 |
| 分治合併 | O(N log k) | O(log k) | 遞歸棧空間 |
| 最小堆 | O(N log k) | O(k) | 推薦,代碼簡潔 |
dummy 節點簡化頭節點處理Compare 實現最小堆(默認 priority_queue 為最大堆)2N 次堆操作