23. 合并K个排序链表
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
解题思路: 合并K个链表可以先合并两个链表,然后反复的将K个链表折半,在折半的过程中,需要考虑待合并的链表数的奇偶性,这里参考了网友Grandyang的写法,从(n + 1) / 2
开始合并,然后下一次需要合并的链表长度也即为(n + 1) / 2
,将链表的奇偶数统一处理了。时间复杂度为
O
(
l
o
g
n
)
O(logn)
O(logn).
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode *headA, ListNode *headB) {
if (!headA) return headB;
if (!headB) return headA;
ListNode *res = NULL, *cur = NULL;
while (headA && headB) {
int val;
if (headA->val < headB->val) {
val = headA->val;
headA = headA->next;
} else {
val = headB->val;
headB = headB->next;
}
if (!res) {
res = new ListNode(val);
cur = res;
} else {
cur->next = new ListNode(val);
cur = cur->next;
}
}
while (headA) {
cur->next = new ListNode(headA->val);
headA = headA->next;
cur = cur->next;
}
while (headB) {
cur->next = new ListNode(headB->val);
headB = headB->next;
cur = cur->next;
}
return res;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.empty()) return NULL;
int n = lists.size();
while (n > 1) {
int m = (n + 1) / 2;
for (int k = 0; k < n / 2; ++k) {
lists[k] = mergeTwoLists(lists[k], lists[k + m]);
}
n = m;
}
return lists[0];
}
};
上面的代码在两个链表的合并过程中,是通过创建新节点合并链表的,下面写一个直接摘取链表上节点的合并链表。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode *headA, ListNode *headB) {
if (!headA) return headB;
if (!headB) return headA;
ListNode *dummy = new ListNode(-1), *cur = dummy;
while (headA && headB) {
if (headA->val < headB->val) {
cur->next = headA;
cur = headA;
headA = headA->next;
} else {
cur->next = headB;
cur = headB;
headB = headB->next;
}
}
if (headA) cur->next = headA;
if (headB) cur->next = headB;
ListNode *res = dummy->next;
delete dummy;
return res;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.empty()) return NULL;
int n = lists.size();
while (n > 1) {
int m = (n + 1) / 2;
for (int k = 0; k < n / 2; ++k) {
lists[k] = mergeTwoLists(lists[k], lists[k + m]);
}
n = m;
}
return lists[0];
}
};