LeetCode合并两个有序链表:这段AC代码的工作原理解析
我正在解决LeetCode上的「合并两个有序链表」问题,题目要求合并两个已排序的链表,拼接原有节点形成新的有序链表并返回其头节点。参考了一段AC代码,现解析其工作原理,代码如下:
class Solution: def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: cur = dummy = ListNode() # * while list1 and list2: # ** if list1.val < list2.val: cur.next = list1 list1, cur = list1.next, list1 # *** else: cur.next = list2 list2, cur = list2.next, list2 if list1 or list2: # **** cur.next = list1 if list1 else list2 return dummy.next # *****
针对代码中带星号的部分,逐一解答疑问:
疑问1:
ListNode()是函数吗?它的作用是什么?
不是函数,是链表节点类的构造方法。ListNode()会创建一个空的哑节点,它没有实际数值,作用是避免处理合并后链表头节点为空的边界情况——不用纠结第一个节点来自list1还是list2,直接从哑节点的next开始构建结果链表即可。疑问2:
while list1 and list2是否表示当list1和list2都不为空时执行循环?
对的。只有当list1和list2当前都指向有效节点(不是None)时,才进入循环比较节点值,选择更小的节点加入结果链表。只要其中一个链表遍历完毕,循环就停止。疑问3:
list1, cur=list1.next, list1是不是表示将list1指向其下一个节点,同时cur指向原来的list1节点?
完全正确。这是Python的并行赋值,右边的表达式会先全部计算完成,再赋值给左边变量。先拿到list1.next和当前的list1,然后把list1移动到下一个节点,同时cur移动到刚才选中的list1节点上,方便下一次循环继续拼接新节点。疑问4:
if list1 or list2: cur.next = list1 if list1 else list2是否表示当其中一个链表为空时,将cur的下一个节点指向非空的链表?
没错。循环结束后,必然有一个链表已经遍历完,剩下的非空链表所有节点都是有序且大于当前结果链表最后一个节点的,所以直接把cur的next指向这个非空链表的剩余部分即可,无需逐个节点遍历。疑问5:
return dummy.next:我以为要返回整个合并后的链表,这不是只返回一个节点吗?
链表是通过节点的next指针串联起来的,返回dummy.next就是返回合并后链表的第一个有效节点,从这个节点开始,顺着next指针就能遍历整个合并后的链表。dummy是我们一开始创建的空节点,它的next才是真正的结果链表头。
内容的提问来源于stack exchange,提问作者kakashiz yo

