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
题源:https://leetcode-cn.com/problems/merge-k-sorted-lists/
代码:
法一:采用优先队列
学习要点:指针先开辟一个节点,而不是直接定义一个空指针,这样头结点就会有next指针。
学习要点
/** * 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 { struct bmp { bool operator()(ListNode* a, ListNode* b) { return a->val>=b->val; } }; public: ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode head(0,nullptr); // 注意!注意!这个head这是一个节点,不是指针 ListNode* cur= & head; // 注意!注意!cur是指针,并且将head节点的地址赋值给它 ,*开头表示指针 priority_queue<ListNode*, vector<ListNode*>, bmp> Q; for(auto i: lists) if (i!=NULL) Q.push(i); // 必须判断是否是空,否则上面比较函数会出错,后面p->next也会出错 while(!Q.empty()) { ListNode* p=Q.top(); Q.pop(); cur->next=p; cur=cur->next; if(p->next!=NULL) Q.push(p->next); } return head.next; // 因为是节点,所以是.next } };
法二:
归并排序
/** * 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 { ListNode* mergelist(ListNode* a, ListNode* b) { ListNode* head=new ListNode(-1); // 此处写法需要学习!!!!! ListNode* cur=head; while(a!=NULL && b!=NULL) { if (a->val<=b->val) {cur->next=a; a=a->next;} else {cur->next=b; b=b->next;} cur=cur->next; // 老是忘记自我移动 } if(a!=NULL) cur->next=a; else if(b!=NULL) cur->next=b; return head->next; } ListNode* merge(vector<ListNode*> s,int l,int r) { if (l==r) return s[l]; if (l>r) return NULL; int mid=(l+r)/2; return mergelist(merge(s,l,mid),merge(s,mid+1,r)); } public: ListNode* mergeKLists(vector<ListNode*>& lists) { return merge(lists,0,lists.size()-1); } };