leetcode-链表排序

链表不同与数组,因为有方向,所以和数组排序能用很多方法不同,比较适合的就是归并排序。

这里是学习的灵神的方法:在刚开始学习积累的时候,建议在B站先看灵神的解读【反转链表【基础算法精讲 06】-哔哩哔哩】 https://b23.tv/63r1l12,先不看代码,自己写,然后看题解。

归并排序(分治)

class Solution:
    # 876. 链表的中间结点(快慢指针)
    def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = fast = head
        while fast and fast.next:
            pre = slow  # 记录 slow 的前一个节点
            slow = slow.next
            fast = fast.next.next
        pre.next = None  # 断开 slow 的前一个节点和 slow 的连接
        return slow

    # 21. 合并两个有序链表(双指针)
    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 加到新链表中
                list1 = list1.next
            else:  # 注:相等的情况加哪个节点都是可以的
                cur.next = list2  # 把 list2 加到新链表中
                list2 = list2.next
            cur = cur.next
        cur.next = list1 if list1 else list2  # 拼接剩余链表
        return dummy.next

    def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 如果链表为空或者只有一个节点,无需排序
        if head is None or head.next is None:
            return head
        # 找到中间节点 head2,并断开 head2 与其前一个节点的连接
        # 比如 head=[4,2,1,3],那么 middleNode 调用结束后 head=[4,2] head2=[1,3]
        head2 = self.middleNode(head)
        # 分治
        head = self.sortList(head)
        head2 = self.sortList(head2)
        # 合并
        return self.mergeTwoLists(head, head2)

整体是一个递归的思想,这个sortList函数首先把一个链表一分为二(采用快慢指针找链表中点,然后断开中点和后面一个节点的连接)。然后对这个被分成两段的链表,要得到它们的排序新链表,也要调用sortList函数,直到递归到只有一个节点或者空节点,就不用排序了。

(1)把链表递归一分为二

(2)递归直到分到最小,返回合并后的,一层层全部合并完,在合并的过程中完成了排序。

时间复杂度:O(nlogn)     空间复杂度:O(logn)[递归的深度]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值