Leetcode-23-合并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;
}

由于此题目是将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;
}

猜你喜欢

转载自blog.csdn.net/Djsnxbjans/article/details/128265929