题目描述:
给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
解题思路:
思路一:
将所有链表的元素插入vector中,然后将vector排序,再重新形成新的链表
时间复杂度:O(N+Log(N))),空间复杂度O(2N)
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0)
{
return nullptr;
}
vector<int> res;
for(int i = 0; i < lists.size(); i++)
{
ListNode* cur = lists[i];
while(cur)
{
res.push_back(cur->val);
cur = cur->next;
}
}
if(res.size() == 0) return nullptr;
sort(res.begin(), res.end());
ListNode* NewNode = new ListNode(res[0]);
ListNode* cur = NewNode;
for(int i = 1; i < res.size(); i++)
{
cur->next = new ListNode(res[i]);
cur = cur->next;
}
return NewNode;
}
};
思路二:
首先用优先级队列建小堆,向其中插入每个链表的头节点,然后从堆顶取出元素,形成新的链表,再将该元素的下一个元素插入堆中,然后从堆顶取出元素,形成新的链表.....如此循环下去,直至所有的链表都空了
优先队列中的元素个数最多是 k,所以一次 push 或者 pop 方法的时间复杂度是 O(logk);所有的链表节点都会被加入和弹出优先级队列,所以算法整体的时间复杂度是 O(Nlogk),其中 k 是链表的条数,N 是这些链表的节点总数。空间复杂度 O(k)。
//自定义比较规则
struct cmp{
bool operator()(ListNode *a,ListNode *b){
return a->val > b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0) return nullptr;
ListNode* res = new ListNode(-1); //虚拟头节点
ListNode* p = res;
priority_queue<ListNode*, vector<ListNode*>,cmp> pq; //优先队列,创建最小堆
//将k个链表的头节点加入最小堆
for (auto tmp : lists) {
if (tmp != nullptr)
pq.push(tmp);
}
while (!pq.empty()) {
//获取最小节点,并将其出队
ListNode* node = pq.top();
pq.pop();
if (node->next != nullptr) {
pq.push(node->next);
}
//将最小节点放入结果链表中
p->next = node;
//p指针不断前进
p = p->next;
}
return res->next;
}