【LeetCode & 剑指offer刷题】链表题7:25 合并两个排序的链表(系列)(21. Merge Two Sorted Lists)
【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
21. Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input:
1->2->4, 1->3->4
Output:
1->1->2->3->4->4
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/*
联系合并两个排序的数组,temp[k++] = (a[i]<b[j])? a[i++] : b[j++]
*/
class
Solution
{
public
:
ListNode
*
mergeTwoLists
(
ListNode
*
l1
,
ListNode
*
l2
)
{
if
(
l1
==
nullptr
)
return
l2
;
if
(
l2
==
nullptr
)
return
l1
;
ListNode prehead
(
0
);
//头结点前面附加一结点(
当原链表头结点可能会变化时都可以考虑使用prehead
)
ListNode
*
p
=
&
prehead
;
//新链表结点指针
for
(;
l1
!=
nullptr
&&
l2
!=
nullptr
;
p = p->next
)
//比较l1和l2各结点大小,归并
{
if
(
l1
->
val
<
l2
->
val
)
{
p
->next = l1
;
//下一个结点指向l1结点
l1
= l1->next;
}
else
{
p
->
next
=
l2
;
l2
=
l2
->
next
;
}
}
if
(
l1
!=
nullptr
)
p->next
=
l1
;
//处理剩余结点
if
(
l2
!=
nullptr
)
p
->
next
=
l2
;
return
prehead.next; //返回头结点指针
}
};
23
.
Merge k Sorted Lists
(hard)
Merge
k
sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output:
1->1->2->3->4->4->5->6
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
//多次用merge2lists的方法
class
Solution
{
public
:
ListNode
*
mergeKLists
(
vector
<
ListNode
*>&
lists
)
{
if
(
lists
.
empty
())
return
nullptr
;
/* ListNode* p = lists[0]; //初始化为第一个链表头指针
for(int i = 1; i<lists.size(); i++) //归并次数为lists.size()
{
p = mergeTwoLists(p, lists[i]);
}
return p;*/
//很耗时
/*
例:
len=5,list[0],list[1],list[2],list[3],list[4]
len/2 = 5/2 = 2;
i=0, (0,4)
i=1, (1,3)
(len+1)/2 = 3,保留 list[0],list[1],list[2],新len=3
*/
while
(
lists
.
size
()
>
1
)
{
int
len
=
lists
.
size
(); //当前链表数量
for
(
int
i
=
0
;
i
<
len
/
2
;
i
++)
//改进为不断二分归并,归并次数可以减少为n/2 + n/4 + ... +1
{
lists
[i] = mergeTwoLists(lists[i], lists[len - i - 1]);
//首尾对应归并
}
lists
.
resize
((
len + 1)/2
);
//新链表数量
}
return
lists
[
0
];
}
private
:
ListNode
*
mergeTwoLists
(
ListNode
*
l1
,
ListNode
*
l2
)
{
if
(
l1
==
nullptr
)
return
l2
;
//可加上特殊情况:如果l1=l2,直接返回l1
if
(
l2
==
nullptr
)
return
l1
;
ListNode prehead
(
0
);
//头结点前面附加一结点
ListNode
*
p
=
&
prehead
;
//新链表结点指针
for
(;
l1
!=
nullptr
&&
l2
!=
nullptr
;
p
=
p
->
next
)
//比较l1和l2各结点大小,归并
{
if
(
l1
->
val
<
l2
->
val
)
{
p
->
next
=
l1
;
//下一个结点指向l1结点
l1
=
l1
->
next
;
}
else
{
p
->
next
=
l2
;
l2
=
l2
->
next
;
}
}
if
(
l1
!=
nullptr
)
p
->
next
=
l1
;
//处理剩余结点
if
(
l2
!=
nullptr
)
p
->
next
=
l2
;
return
prehead
.
next
;
//返回头结点指针
}
};
Sort List
Sort a linked list in
O(n log n) time using constant space complexity.
Example 1:
Input:
4->2->1->3
Output:
1->2->3->4
Example 2:
Input:
-1->5->3->4->0
Output:
-1->0->3->4->5
C+
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/*
问题:对链表排序
方法:归并排序
先用快慢指针法找到链表中部位置,对左右子链表递归处理,进行分割和归并
O(nlogn) O(1)
*/
class
Solution
{
public
:
ListNode
*
sortList
(
ListNode
*
head
)
{
if (!head || !head->next) return head;
ListNode
*
slow
=
head
,
*
fast
=
head
,
*
pre
=
head
;
while
(fast && fast->next)
{
pre
=
slow
;
slow
=
slow
->
next
;
fast
=
fast
->
next
->
next
;
}
//
退出循环时,
fast或fast->next = nullptr,slow
指向中部位置
pre
->
next
=
NULL
;
//
将左右子链表断开处理
return
merge
(
sortList
(
head
),
sortList
(
slow
));
//
归并左右子链表
}
ListNode
*
merge
(
ListNode
*
l1
,
ListNode
*
l2
)
{
if
(
l1
==
nullptr
)
return
l2
;
if
(
l2
==
nullptr
)
return
l1
;
ListNode prehead
(
0
);
//
头结点前面附加一结点(当原链表头结点可能会变化时都可以考虑使用
prehead
)
ListNode
*
p
=
&
prehead
;
//
新链表结点指针
for
(;
l1
!=
nullptr
&&
l2
!=
nullptr
;
p
=
p
->
next
)
//
比较
l1
和
l2
各结点大小,归并
{
if
(
l1
->
val
<
l2
->
val
)
{
p
->
next
=
l1
;
//
下一个结点指向
l1
结点
l1
=
l1
->
next
;
}
else
{
p
->
next
=
l2
;
l2
=
l2
->
next
;
}
}
if
(
l1
!=
nullptr
)
p
->
next
=
l1
;
//
处理剩余结点
if
(
l2
!=
nullptr
)
p
->
next
=
l2
;
return
prehead
.
next
;
//
返回头结点指针
}
};