排序链表,递归内要对链表进行截断

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,我们明确地将原始链表分割成两个独立的子链表,每个子链表都有一个明确的开始和结束。这样,我们就可以独立地对每个子链表进行排序,然后再将它们合并成一个有序的链表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值