LeetCode21.合并两个有序链表
题目
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
输入:l1 = [], l2 = []
输出:[]
输入:l1 = [], l2 = [0]
输出:[0]
提示:
两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列
解题思路
递归
例:[1,2,4],[1,3,4]
第一次递归:1 ([2,4],[1,3,4])
第二次递归:1,1([2,4],[3,4])
第三次递归:1,1,2([4],[3,4])
第四次递归:1,1,2,3([4],[4])
第五次递归:1,1,2,3,4([4])
第六次递归:1,1,2,3,4,4
时间复杂度:O(n+m)
空间复杂度:O(n+m)
其中 n 和 m 分别为两个链表的长度。
迭代
定义一个哑节点(哨兵节点)用来穿串,
循环两个链表,其中一个遍历完了结束,
遍历过程中判断哪个值小就先穿哪个,
最后再判断下两个链表还有没有剩的,
把剩下的一次性全部串上。
时间复杂度:O(n+m)
空间复杂度:O(1)
代码
// 迭代
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
// 哨兵节点
prehead := &ListNode{}
// 保存链表头指针位置
result := prehead
// 当两链表不为空的时候循环进行比较
for l1 != nil && l2 != nil{
if l1.Val < l2.Val {
prehead.Next = l1
l1 = l1.Next
}else{
prehead.Next = l2
l2 = l2.Next
}
prehead = prehead.Next
}
// 循环比较后如果还存在剩余元素,指针直接连接剩余有序链表
if l1 != nil {
prehead.Next = l1
}
if l2 != nil {
prehead.Next = l2
}
return result.Next
}
// 递归
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
// 如果一个链表为空,直接返回另一个剩余链表
if l1 == nil{
return l2
}else if l2 == nil{
return l1
// 比较两链表当前节点值大小,进一步切片
// 将当前递归链表连接下一步递归结果
// 返回当前值小的节点
}else if l1.Val < l2.Val{
l1.Next = mergeTwoLists(l1.Next,l2)
return l1
}else{
l2.Next = mergeTwoLists(l1,l2.Next)
return l2
}
}