合并两个有序链表
题目:
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
思路:
鉴于上个题目两个数相加之和的总结,这次不在定义两个临时变量指向两个链表,直接遍历两个链表
1.定义一个带头结点的链表
2.遍历两个链表l1、l2,比较两个链表当前结点的值的大小,小结点直接插入结果链表,同时向后移动该链表,循环此过程直到其中一个链表为NULL结束。
3.将不为NULL的链表插入到结果链表上
代码:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode res(-1);
ListNode* pRes = &res;
while (l1 != NULL && l2 != NULL)
{
if (l1->val > l2->val)
{
pRes->next = l2;
l2 = l2->next;
}
else {
pRes->next = l1;
l1 = l1->next;
}
pRes = pRes->next;
}
if (l1 == NULL)
{
pRes->next = l2;
}
if (l2 == NULL)
{
pRes->next = l1;
}
return res.next;
}
总结:
有了上一道题目优化经验,就可以直接省去一些思考的中间环节,直接写出一次性满意的代码。
合并K个排序链表
题目
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
思路:
1.合并K个链表就是选择两个先合并成一个链表再将合成后的链表与剩余的链表一一合并得出最终的结果
2.合并两个链表直接调用上到题目完成的函数。
代码:
常规思路:
ListNode* mergeKLists(vector<ListNode*>& lists) {
ListNode res(-1);
ListNode* pRes = &res;
for (size_t i = 0; i < lists.size(); i++)
{
pRes->next = mergeTwoLists(lists[i], pRes->next);
}
return res.next;
}
递归思路:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int size = lists.size();
if (size == 0)
{
return NULL;
}
if (size == 1)
{
return lists[0];
}
for (int i = 0; i < size / 2; i++)
{
lists[i] = mergeTwoLists(lists[i], lists[size - i - 1]);
lists.pop_back();
}
ListNode res(-1);
res.next = mergeKLists(lists);
return res.next;
}
总结
1.常规思路就是将每一个链表逐一合并。
2.递归思路是将链表两两分成一组进行合并,最终将所有的分组再次进行两两合并,直到合并为一个链表为止,这就是递归分治的思路
3.对比两种思路:递归思路减少了合并的次数。