将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
- 输入: l 1 = [ 1 , 2 , 4 ] , l 2 = [ 1 , 3 , 4 ] l1 = [1,2,4], l2 = [1,3,4] l1=[1,2,4],l2=[1,3,4]
- 输出: [ 1 , 1 , 2 , 3 , 4 , 4 ] [1,1,2,3,4,4] [1,1,2,3,4,4]
方法一:递归
在保证两个链表非空的情况下,可以递归地执行合并操作:
{
l
i
s
t
1
[
0
]
+
m
e
r
g
e
(
l
i
s
t
1
[
1
:
]
,
l
i
s
t
2
)
l
i
s
t
1
[
0
]
<
l
i
s
t
2
[
0
]
l
i
s
t
2
[
0
]
+
m
e
r
g
e
(
l
i
s
t
1
,
l
i
s
t
2
[
1
:
]
)
o
t
h
e
r
w
i
s
e
\begin{cases} list1[0]+merge(list1[1:],list2) \quad list1[0]<list2[0]\\ list2[0]+merge(list1,list2[1:]) \quad otherwise\\ \end{cases}
{list1[0]+merge(list1[1:],list2)list1[0]<list2[0]list2[0]+merge(list1,list2[1:])otherwise
即:两个链表头部数值较小的结点与剩下元素的 m e r g e merge merge结果进行合并。
//递归法
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
if (list1 == NULL || list2 == NULL) {
return list1 == NULL ? list2 : list1;
}
//此时list1和list2都不为空
else if (list1->val < list2->val) {
//当前list1的头节点保留,该结点的next指针指向剩余元素的merge结果
list1->next = mergeTwoLists(list1->next, list2);
return list1;
}
else {
list2->next = mergeTwoLists(list1,list2->next);
return list2;
}
}
时间复杂度: O ( n + m ) O(n+m) O(n+m),其中 n n n 和 m m m 分别为两个链表的长度
空间复杂度:
O
(
n
+
m
)
O(n+m)
O(n+m),其中
n
n
n 和
m
m
m 分别为两个链表的长度。递归调用 mergeTwoLists
函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时 mergeTwoLists
函数最多调用
n
+
m
n+m
n+m 次,因此空间复杂度为
O
(
n
+
m
)
O(n+m)
O(n+m)。
方法二:迭代
迭代的思路和递归的思路类似,只是迭代法是借助一个新的节点,依次指向两个链表中的节点,将其按照大小顺序连接起来。当 l 1 l1 l1 和 l 2 l2 l2 都不是空链表时,判断 l 1 l1 l1 和 l 2 l2 l2哪一个链表的头节点的值更小,将较小值的节点添加到结果里,当一个节点被添加到结果里之后,将对应链表中的节点向后移一位。
//迭代法
ListNode* mergeTwoLists2(ListNode* l1, ListNode* l2) {
//定义一个新指定,指向结果链表
ListNode* ResHead = new ListNode(-1);
//定义一个新指针,指向结果链表的尾部,通过该指针链接两个链表中的元素
ListNode* ResRear = ResHead;
while (l1 != NULL && l2 != NULL) {
if (l1->val < l2->val) {
ResRear->next = l1;
l1 = l1->next;
}
else
{
ResRear->next = l2;
l2 = l2->next;
}
ResRear = ResRear->next;
}
//当跳出while循环时,l1和l2有一个被全部合并,另一个可能还有元素,可以直接将链表指向未合并完的链表
ResRear->next = l1 == NULL ? l2 : l1;
return ResHead->next;
}
时间复杂度: O ( n + m ) O(n+m) O(n+m),其中 n n n 和 m m m 分别为两个链表的长度
空间复杂度: O ( 1 ) O(1) O(1)
自己是按照迭代的思路来求解问题,但是关于循环的条件判断一直理不清,没有想到利用 l i s t 1 list1 list1 和 l i s t 2 list2 list2 这两个指针来遍历自身,还要努力呀!