题目
leetcode 21. 合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
难度:简单
题目分析:重点便是有序二字。有序的链表题在删除重复元素、合并等问题,都难度不大。
同时记得考虑特殊输入,两个均为空链表,一个为空链表的情形。
解法一:递归
给定链表 l1 和 l2, 比较第一个元素,如 l1 第一个元素小于 l2 第一个元素,那返回的列表,表头就是 l1 第一个元素。
少了一个元素的 l1 链表 和 l2 链表,此时又是一个排序问题,于是,我们可以调用我们正在编写(虽然还没完成,但有这个功能啊!),返回的一定是个排好序的链表,接上即可,于是,求解代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 is None:
return l2
if l2 is None:
return l1
if l1.val <= l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
运行结果:
搞不明白,一样的代码,就是运行时间不一样……
解法二: 非递归
建立一个新链表,然后依次从两个链表摘元素接上。这种解法的空间会多一个指针,其实不占空间。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
head = ListNode(-1)
cur = head
p1 = l1
p2 = l2
while p1 and p2:
if p1.val <= p2.val:
cur.next = p1
p1 = p1.next
else:
cur.next = p2
p2 = p2.next
cur = cur.next
if p1 is None:
cur.next = p2
else:
cur.next = p1
return head.next
运行结果:
可能没充钱……
解法三 非递归,插入
以一个链表为基准,另一个链表依次插入。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 is None:
return l2
if l2 is None:
return l1
if l1.val <= l2.val:
head = l1
else:
head = l2
p1 = l1
p2 = l2
while p2 is not None:
if p2.val < p1.val
while (p2.next is not None) and (p2.next.val < p1.val):
p2 = p2.next
# 出来之后,就找到 p2.val 大于 p1的
l2 = p2.next
p2.next = p1
else: # 这里是 p1 < p2, 因此找p2的插入位置
while (p1.next is not None) and (p1.next.val <= p2.val):
p1 = p1.next
l2 = p2.next
p2.next = p1.next
p1.next = p2
# 更新,l2的表, 剩下的点
p2 = l2
return head
运行结果:
这个程序有点绕……
题外话
刚查看了Leetcode提交的各种不同运行时间的代码,发现,有些人跟我使用一模一样的代码,时间却只有20ms, 我的程序的一半……这其实说明了,这个网站的时间,仅供参考……不过还好,排名第一的程序,16ms, 用的就是非递归。这至少说明,非递归程序会比非递归程序快。
递归虽然可以快速求解问题,然而却不是解法最快的方法。可以先快速求解问题,不过为了更快解答,还是需要非递归的解法。虽然我的代码,运行结果看不出非递归快,但是,至少提交记录证明了。