Leetcode 21. 合并两个有序链表 Python 以及找好解法的方法!
题目
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
自己解法(慢慢慢)
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
lnOutNode = ListNode(None)
lnLastNode = ListNode(None)
lnOldLastNode = ListNode(None)
lnPreNode = l1
lnRearNode = l2
lnOutNode.next = lnLastNode
#lnOutNode.next = lnOldLastNode
if l1 == None and l2 == None:return None
while(True):
lnOldLastNode = lnLastNode
lnLastNode = ListNode(None)
if lnPreNode == None:
lnLastNode = lnRearNode
lnOldLastNode.next = lnLastNode
break
elif lnRearNode == None:
lnLastNode = lnPreNode
lnOldLastNode.next = lnLastNode
break
if lnPreNode.val > lnRearNode.val:
lnLastNode.val = lnRearNode.val
lnRearNode = lnRearNode.next
else:
lnLastNode.val = lnPreNode.val
lnPreNode = lnPreNode.next
lnOldLastNode.next = lnLastNode
return lnOutNode.next.next
思路:
重温《算法》一书链表部分,学习了保存指向尾节点链接的方法,拍下来供大家参考,侵删。
尾部设置两个Node对象,oldlast和last 。
last负责获得两条链表的最小值并存储
oldlast负责螳螂捕蝉黄雀在后,一旦last搞定,就把它吞掉变为自己。
顺序:(着实杀了我一批脑细胞,请原谅我的菜)
1、先设置好输出node的指向(next),将其指向lastnode
2、oldlast 吞掉 last
3、新的last开始获得所需要的值
4、oldlast把指向(next)引到last上
5、循环中设置退出机制,只要两条给出的链表有一条结束,直接把另一条接到输出Node的后面,结束循环
6、最前面可加上两条链表都为None时直接输出None
注:1、我的输出为lnOutNode.next.nxet,是因为前两个节点都没设置值,值均为None
2、后知后觉,上文中lnPreNode和lnRearNode其实没有必要设置,直接用l1,l2代替更好,下附修改代码:
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
lnOutNode = ListNode(None)
lnLastNode = ListNode(None)
lnOldLastNode = ListNode(None)
lnOutNode.next = lnLastNode
#lnOutNode.next = lnOldLastNode
if l1 == None and l2 == None:return None
while(True):
lnOldLastNode = lnLastNode
lnLastNode = ListNode(None)
if l1 == None:
lnLastNode = l2
lnOldLastNode.next = lnLastNode
break
elif l2 == None:
lnLastNode = l1
lnOldLastNode.next = lnLastNode
break
if l1.val > l2.val:
lnLastNode.val = l2.val
l2 = l2.next
else:
lnLastNode.val = l1.val
l1 = l1.next
lnOldLastNode.next = lnLastNode
return lnOutNode.next.next
知识点
1、Python不支持do〜while语法、while(无限循环)和break组合起来替换 do ~ while
2、Python没有Null , 只有None 一开始不太理解啥是None,学习了。
3、吐槽 leetcode每次runtime时长不一样啊!!同一个代码误差近20%
大神解法
1、迭代
class Solution:
def mergeTwoLists(self, a, b):
if a and b:
if a.val > b.val:
a, b = b, a
a.next = self.mergeTwoLists(a.next, b)
return a or b
给跪了,5行迭代。
解释:
1、python两个数值互换 a,b=b,a
互换的解释:https://blog.****.net/qq_33414271/article/details/78522235
2、**or中, 至少有一个非0时,返回第一个非0,**这点第一次看没看懂
如果两个列表都是非空的,首先确保a开始时更小,因此使用它的头部,并合并后面的余数。否则,交换ab顺序,让更小的为a。如果一个或两个都是空的,就返回非空值(优先返回前值a)。
最后总会出现一条链表有值,一条链表没值的情况,这时,会return a or b 返回最后一位有值的那个值。如果不加这个or,程序运行总会少一位!!
最后再感叹下,这位大哥怎么想出来的,不是人脑袋。公示他!
粗暴排序
class Solution:
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
l = list()
while(l1!=None):
l.append(l1.val)
l1 = l1.next
while(l2!=None):
l.append(l2.val)
l2 = l2.next
return sorted(l)
哪条链表上还有活口,就往输出里塞,最后进行粗暴排序(对象也能排序,长见识了)
以上是最震撼我的解法(尤其是第一个大佬),有其他解法欢迎补充。
找好解法的方法
1、建议去原版leetcode的评论区找,都是大神 (可搜对应语言的名字)
2、Leetcode提交后有个图表,可以点开查看runtime在前面的解法
但是国内外的runtime非常看天,分不出来到底哪种解法更优,可能只能判断算法的时间复杂度了,耗时耗力。国外相对国内网站的网页响应时间更慢,但是结果相对更准确。