顺序合并
大家应该对合并两个升序链表很熟悉,它的算法如下:
struct ListNode* MergeList(struct ListNode* head1, struct ListNode* head2)
{
struct ListNode* cur1 = head1, * cur2 = head2;
struct ListNode* newhead = NULL, * tail = NULL;
while (cur1 && cur2)
{
if (cur1->val <= cur2->val)
{
if (newhead == NULL)
{
newhead = tail = cur1;
}
else
{
tail->next = cur1;
tail = cur1;
}
cur1 = cur1->next;
}
else
{
if (newhead == NULL)
{
newhead = tail = cur2;
}
else
{
tail->next = cur2;
tail = cur2;
}
cur2 = cur2->next;
}
}
while (cur1)
{
if (newhead == NULL)
{
newhead = tail = cur1;
}
else
{
tail->next = cur1;
tail = cur1;
}
cur1 = cur1->next;
}
while (cur2)
{
if (newhead == NULL)
{
newhead = tail = cur2;
}
else
{
tail->next = cur2;
tail = cur2;
}
cur2 = cur2->next;
}
return newhead;
}
由于此题目是将K个升序链表合并,我们可以先将前两个链表合并再与第三个合并…再与第K个合并。
下面看代码:
struct ListNode* MergeList(struct ListNode* head1, struct ListNode* head2)
{
struct ListNode* cur1 = head1, * cur2 = head2;
struct ListNode* newhead = NULL, * tail = NULL;
while (cur1 && cur2)
{
if (cur1->val <= cur2->val)
{
if (newhead == NULL)
{
newhead = tail = cur1;
}
else
{
tail->next = cur1;
tail = cur1;
}
cur1 = cur1->next;
}
else
{
if (newhead == NULL)
{
newhead = tail = cur2;
}
else
{
tail->next = cur2;
tail = cur2;
}
cur2 = cur2->next;
}
}
while (cur1)
{
if (newhead == NULL)
{
newhead = tail = cur1;
}
else
{
tail->next = cur1;
tail = cur1;
}
cur1 = cur1->next;
}
while (cur2)
{
if (newhead == NULL)
{
newhead = tail = cur2;
}
else
{
tail->next = cur2;
tail = cur2;
}
cur2 = cur2->next;
}
return newhead;
}
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize)
{
if (listsSize == 0)
{
return NULL;
}
struct ListNode* newhead = lists[0];
for (int i = 1; i < listsSize; i++)
{
newhead = MergeList(newhead, lists[i]);
}
return newhead;
}
分治合并
由于,我们很熟悉两个升序链表的合并,所以这种思路就是,将问题转化为两个升序链表合并。
首先,对lists数组进行分割,分割成等大的两段,分别将这两段中的所有链表合并成为一个链表,最终将两个链表合并。(有种归并排序的感觉。。。)
下面看代码:
struct ListNode* MergeList(struct ListNode* head1, struct ListNode* head2)
{
struct ListNode* cur1 = head1, * cur2 = head2;
struct ListNode* newhead = NULL, * tail = NULL;
while (cur1 && cur2)
{
if (cur1->val <= cur2->val)
{
if (newhead == NULL)
{
newhead = tail = cur1;
}
else
{
tail->next = cur1;
tail = cur1;
}
cur1 = cur1->next;
}
else
{
if (newhead == NULL)
{
newhead = tail = cur2;
}
else
{
tail->next = cur2;
tail = cur2;
}
cur2 = cur2->next;
}
}
while (cur1)
{
if (newhead == NULL)
{
newhead = tail = cur1;
}
else
{
tail->next = cur1;
tail = cur1;
}
cur1 = cur1->next;
}
while (cur2)
{
if (newhead == NULL)
{
newhead = tail = cur2;
}
else
{
tail->next = cur2;
tail = cur2;
}
cur2 = cur2->next;
}
return newhead;
}
struct ListNode* mergeKLists1(struct ListNode** lists, int begin, int end)
{
if (begin >= end)
{
return NULL;
}
int mid = begin + (end - begin) / 2;
struct ListNode* ret1 = mergeKLists1(lists, begin, mid);
struct ListNode* ret2 = mergeKLists1(lists, mid+1, end);
return MergeList(ret1, ret2);
}
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize)
{
if (listsSize == 0)
{
return NULL;
}
return mergeKLists1(lists, 0, listsSize - 1);
}
循环选结点合并
这种思路,与合并两个升序链表的思想一致,区别就是,每次从listsSize个链表中选出最小的结点。
下面看代码:
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize)
{
if (listsSize == 0)
{
return NULL;
}
struct ListNode* newhead=NULL, * tail=NULL;
int flag = 1;
while (flag)
{
int min = 10001;
int minlog = -1;
flag = 0;
for (int i = 0; i < listsSize; i++)
{
if (lists[i] == NULL)
{
continue;
}
if (lists[i]->val < min)
{
flag = 1;
min = lists[i]->val;
minlog = i;
}
}
if (flag)
{
if (newhead == NULL)
{
newhead = tail = lists[minlog];
lists[minlog] = lists[minlog]->next;
}
else
{
tail->next = lists[minlog];
tail = lists[minlog];
lists[minlog] = lists[minlog]->next;
}
}
}
return newhead;
}