148. 排序链表
class Solution:
def sortList(self, head: ListNode) -> ListNode:
if not head or not head.next: return head #单节点或者无节点
slow, fast = head, head.next
# fast的作用在这里相当于计算 L//2
while fast and fast.next: # fast只能到倒数第二个
fast, slow = fast.next.next, slow.next
mid = slow.next
slow.next = None #阶段左链条,以免通过递归进入下一循环
#此时slow=3 fast=null
left, right = self.sortList(head), self.sortList(mid)
h = res = ListNode(0)
while left and right:
if left.val < right.val: h.next, left = left, left.next
else: h.next, right = right, right.next
h = h.next
h.next = left if left else right
return res.next
假设我们有一个链表:1 -> 4 -> 3 -> 2。我们想要对这个链表进行排序。
在这个例子中,slow和fast都从头节点开始。fast每次移动两个节点,slow每次移动一个节点。当fast到达链表的末尾时,slow将位于链表的中间。在我们的例子中,slow将指向节点4。
然后,我们通过设置slow.next = None来断开链表,这样我们就有了两个链表:1 -> 4 和 3 -> 2。
现在,我们可以分别对这两个链表进行排序。首先,我们对链表1 -> 4进行排序,得到1 -> 4。然后,我们对链表3 -> 2进行排序,得到2 -> 3。
最后,我们将这两个已排序的链表合并,得到最终的排序链表:1 -> 2 -> 3 -> 4。
为什么我们将无法正确地将链表分开,如果不能分开,那么结果是什么
如果我们没有slow.next = None这一步,那么在尝试对左半部分和右半部分进行排序时,我们将无法正确地将链表分开,这可能会导致错误。因此,slow.next = None是必要的,因为它确保了链表被正确地分割成两半。
如果我们不设置slow.next = None,那么在递归调用sortList函数时,链表将不会被正确地分割。这是因为,对于左半部分的链表,我们期望它的末尾是None,这样我们就知道已经到达了链表的末尾。但是,如果我们不设置slow.next = None,那么左半部分的链表将会包含整个原始链表,这将导致递归调用无法正确地终止,从而可能导致无限循环。
假设我们有一个链表:1 -> 4 -> 3 -> 2。我们想要对这个链表进行排序。如果我们不设置slow.next = None,那么在第一次递归调用sortList函数时,head将会是1,mid将会是3,但是head的链表将会是1 -> 4 -> 3 -> 2,而不是我们期望的1 -> 4。这将导致我们无法正确地对链表进行排序。
重复调用的话,slow不是会被重新赋值吗
每次递归调用sortList函数时,slow和fast都会被重新初始化为头节点。然而,问题在于我们如何定义链表的"结束"。在链表中,我们通常使用None来表示链表的结束。当我们进行递归排序时,我们希望能够清楚地定义每个子链表的开始和结束,这样我们就可以独立地排序它们。
如果我们不设置slow.next = None,那么即使slow在每次递归调用中被重新赋值,左半部分的链表仍然会包含右半部分的节点。这是因为,除非我们明确地断开它们,否则左半部分的最后一个节点(也就是slow)的next将会是右半部分的第一个节点。这意味着,当我们试图对左半部分进行排序时,我们实际上是在对整个链表进行排序,这并不是我们想要的。
通过设置slow.next = None,我们明确地将原始链表分割成两个独立的子链表,每个子链表都有一个明确的开始和结束。这样,我们就可以独立地对每个子链表进行排序,然后再将它们合并成一个有序的链表。