这里是昨天的小尾巴。对我来说好吃力啊,我先是学习了一遍链表,再来弄这个题目。太费时间了啊。
递归有点看不太懂
题目:
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:(这题隐含了,需要按大小排序,并且这里是从前往后逐个比的,谁最先小就是谁(交叉)。还有种理解是全部大小排序都可以)
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
比如:交叉
输入:[3,1,2] [2,3,4]
输出:[2,3,3,1,2,4]
比如:排序
输入:[1,4,5] [1,3,3]
输出[1,1,3,3,4,5] 不是[1,1,3,4,3,5]
参考解答:
1.迭代:
思路:因为两个链表都是有序链表(递增),因此可以很容易地找出两个链表中的最小元素,即比较两个链表表头的元素,时间复杂度是 O(1)的。我们可以利用两个指针——指向两个链表的最小节点,每次比较两个指针所指向节点的值,将值比较小的节点加到新的链表中,然后更新指针,如此循环往复直到到达一个链表的尾部。最后,还需要将另一个链表的剩余部分(如果存在的话)添加到新的链表的尾部。思路:选择一条主链表,同时设置2个指针分别指向2个链表。if判断节点值的大小,通过指针的操作使主链表不断增长。
复杂度分析:
- 时间复杂度:O(m+n),其中,m 为链表 1 的节点数,n为链表 2 的节点数,算法需要遍历两个链表的所有元素
- 空间复杂度:O(1),只需要保存两个引用
-
36 ms 11.8 MB
先看下繁琐版:(不知道哪里出问题运行不起来)
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
res = ListNode(None) # todo 1
dumb_head = res
while l1 and l2:
if l1.val<l2.val:
print('l1.val,l2.val',l1.val,l2.val)
dumb_head.next= l1.next # todo 2
l1 = l1.next
else:
dumb_head.next = l2
l2 = l2.next
node = dumb_head.next
if l1:
dumb_head.next = l1
else:
dumb_head.next = l2 # todo 3
return res.next
class Solution1(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1 and not l2: # l1和l2链表均不存在
return None
elif not l1: # l1链表不存在
return l2
else: # l2链表不存在
return l1
dumb_head=last_node=ListNode(0) # todo 1 上面两句合并
# last_node = ListNode(None)
while l1 and l2:
if l1.val < l2.val: #这里是从前往后逐个比的,谁最先小就是谁
print('l1.val,l2.val', l1.val, l2.val)
last_node.next,l1 = l1,l1.next#todo 2 上面两句合并
else:
last_node.next,l2 = l2,l2.next
last_node = last_node.next
last_node.next=l1 or l2 #todo 3这里代替了上面的if else
return dumb_head.next
if __name__=='__main__':
l1=ListNode([1,4,2])
l2=ListNode([1,3,4])
mm=Solution1().mergeTwoLists(l1,l2)
2.递归
思路:递归的思路和迭代的思路是相同的,都是每次比较两个链表的最小节点,然后对值更小的节点进行操作。不同的是,迭代是从值比较小的节点开始组建新的链表,而递归则是从值比较大的节点开始组建新的链表——递归到其中一个链表的尾部才开始组建新的链表。
复杂度分析:
- 时间复杂度:O(m+n):,其中,m 为链表 1 的节点数,n为链表 2 的节点数,算法需要遍历两个链表的所有元素
- 空间复杂度:O(m+n),额外的空间是由于递归调用占用系统栈的空间,递归的深度最多为 m+n层
Python 实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1 and not l2: # l1和l2链表均不存在
return None
elif not l1 or not l2:
return l1 or l2
if l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1 #l1小的话,就把l1的下一个节点指向l2节点。
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2 #l2小的话,就把12的下一个节点指向l1节点。顺序无关,主要是用谁的.next(类似指针)
3.排序
class Solution3:
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1 and not l2:
return
res = []
q1, q2 = l1, l2
while q1:
res.append(q1)
q1 = q1.next
print(q1) #None
while q2:
res.append(q2)
q2 = q2.next
print(q2)
print(res) #[<__main__.ListNode object at 0x7fc8e36d16a0>, <__main__.ListNode object at 0x7fc8e36d16d8>]
res = sorted(res, key=lambda x: x.val)
return [i.val for i in res]
总结:
1.要注意复杂度的问题,学着分析。
1)递归调用会占用系统栈的空间。递归从后往前看
2)注意python写法
2.python用法之sorted:
1) 列表排序:sorted(list)
2) 元组排序:需要用到参数key。用到隐函数lambda,是固定写法,不要写成别的单词;x表示列表中的一个元素,在这里,表示一个元组,x只是临时起的一个名字,你可以使用任意的名字;x[0]表示元组里的第一个元素,意思就是按照列表中第一个元素排序 。当然第二个元素就是x[1]
#sorted
list_a=[('a',1),('c',3,),('b',4)]
print(sorted(list_a,key=lambda x:x[0])) #按第一个排序 [('a', 1), ('b', 4), ('c', 3)]
print(sorted(list_a,key=lambda x:x[1])) #按第二个排序[('a', 1), ('c', 3), ('b', 4)]
print(sorted(list_a)) # 默认是第一个的 [('a', 1), ('b', 4), ('c', 3)]
print(sorted(list_a,reverse=True)) #倒序 [('c', 3), ('b', 4), ('a', 1)]
3) reverse参数实现倒序排列
3.我依然很菜。