链表归并排序递归调用:传递slow.next与mid的差异及问题解析
归并排序sortList中递归参数的疑问:为什么传mid可行,直接传slow.next不行?
先看你提供的代码片段,问题出在拆分链表后的引用变化上,咱们一步步拆解:
class Solution: def sortList(self, head: ListNode) -> ListNode: if not head or not head.next: return head fast = head.next slow = head while fast and fast.next: fast = fast.next.next slow = slow.next mid = slow.next # 保存后半段链表的头引用 slow.next = None # 拆分链表,前半段到slow结束 l = self.sortList(head) r = self.sortList(slow.next) # 这里传入slow.next会失效,换成mid就正常 return self.merge(l,r) def merge(self, l, r): if not l or not r: return l or r if l.val > r.val: l, r = r, l # get the return node "head" head = pre = l l = l.next while l and r: if l.val < r.val: l = l.next else: nxt = pre.next pre.next = r tmp = r.next r.next = nxt r = tmp pre = pre.next # l and r at least one is None pre.next = l or r return head
关键操作分析
mid的作用:保存拆分前的后半段头节点
当你执行mid = slow.next时,你把当前slow节点的下一个节点(也就是原链表后半段的第一个节点)的引用存在了mid变量里。这时候slow.next还指向有效的后半段链表。slow.next = None:切断链表的关键一步
这行代码的目的是把原链表拆成两个独立的部分:- 前半段:从
head到slow(因为slow.next被置空,前半段在这里结束) - 后半段:原本从
slow.next开始的所有节点,这部分的头节点就是我们之前存在mid里的引用。
- 前半段:从
为什么传入slow.next不行?
在执行slow.next = None之后,slow.next的值已经变成了None。这时候你把slow.next传入递归,相当于给sortList传了一个空链表——原链表的后半段完全没被传入递归函数,自然无法被排序。最终merge的时候,r是空的,结果就只是前半段的排序结果,整个链表的排序肯定出错。
为什么传入mid就正常?
mid保存的是slow.next = None执行之前的引用,也就是原链表后半段的头节点。传入mid时,递归函数拿到的是完整的后半段链表,能正常对其进行归并排序,之后merge前半段和后半段的结果,就能得到正确的排序链表。
核心差异总结
- 传入mid:mid是拆分前后半段链表头的有效引用,指向完整的后半段节点
- 传入slow.next:拆分操作后slow.next变为None,传入的是空链表,无法代表原后半段
内容的提问来源于stack exchange,提问作者Ajinkya Ghadge
相关产品推荐
相关产品推荐

