
这道题我是用最淳朴最简单的思路去做的,用一个while
循环持续地将当前遍历到的最小值加入到合并链表中,while
循环中使用一个for
循环遍历整个指针数组,将其中的最小值和对应下标记录下来,并将其值加入到合并链表中,同时对应的那条链表的指针后移一位。这里我们需要用到一个额外的辅助变量flag
,在每一次执行for
循环之前需要初始化为false
,默认为所有链表都已经遍历到末尾,在for
循环中,如果遇到了还没遍历到末尾的链表,则flag
会被更新为true
,该标志位的作用就是用来标记所有链表是否遍历结束,如果遍历结束就直接跳出外层的while
循环。
cpp
/**
* 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) {
ListNode* result = new ListNode();
ListNode* temp = result;
bool flag = lists.size() == 0 ? false : true;
while(flag){
int min_value = INT_MAX;
int min_index = INT_MAX;
flag = false;
for(int i = 0; i < lists.size(); ++i){
if(!lists[i]){ //若当前遍历到的链表已经遍历到末尾,则直接跳过当前链表
flag = false || flag;
continue;
}
flag = true; //尚有链表没有遍历结束
if(lists[i] -> val < min_value){
min_value = lists[i] -> val; //更新当前节点的最小值
min_index = i; //更新最小值的下标
}
}
if(flag){
temp -> next = new ListNode(min_value);
cout << min_value << endl;
temp = temp -> next;
lists[min_index] = lists[min_index] -> next;
}
}
return result -> next;
}
};
但是这么做的耗时有点太长了,AC之后去看了下灵神的题解,感觉他的第一种思路特别通俗易懂,主要是借用了数据结构本身的特性,利用优先队列进行自动排序,而无需手动排序,因此我们只需要不断地将节点加入到优先队列中即可,这道题需要我们自定义一个排序规则,以对链表节点进行排序,当我们把优先队列的队头元素(队列内的最小值)取出后,我们需要判断队头元素的下一个节点是否为空,若不为空才将下一个节点加入到优先队列中。当所有链表的所有节点都被加入到优先队列中后,我们直接退出循环。
cpp
/**
* 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) {
ListNode* result = new ListNode();
ListNode* temp = result;
// 使用Lambda表达式定义比较规则
auto compare = [] (const ListNode* a, const ListNode* b) {
return a -> val > b -> val; //较小的优先级较高
};
priority_queue<ListNode*, vector<ListNode*>, decltype(compare)> q; //优先队列,存储值较小的排前面
for(auto head : lists){
if(head) q.push(head); //将所有的非空链表头节点入队
}
while(!q.empty()){
temp -> next = new ListNode(q.top() -> val);
cout << q.top() -> val << endl;
if(q.top() -> next) //下个节点不为空才入队
q.push(q.top() -> next);
q.pop();
temp = temp -> next;
}
return result -> next;
}
};