Loading

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
   }
}
posted @ 2021-08-27 15:51  励码万言  阅读(28)  评论(0编辑  收藏  举报