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;
}
  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大理寺j

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值