LeetCode 148. 排序链表(Sort List)

148. 排序链表

📘题目描述

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

    示例 1:

    输入:head = [4,2,1,3]
    输出:[1,2,3,4]
    

    示例 2:

    输入:head = [-1,5,3,4,0]
    输出:[-1,0,3,4,5]
    

    示例 3:

    输入:head = []
    输出:[]

    💡解题思路:归并排序(自顶向下)

    链表不能使用快速排序(因无法随机访问),推荐使用归并排序,尤其适合链表。

    🧠为何选择归并排序?

    • 快速排序需要随机访问,链表效率极低。

    • 归并排序天然适配链表,拆分过程快慢指针即可完成。

    • 时间复杂度 O(n log n),空间复杂度 O(log n)(递归栈)。


    🚩算法流程(自顶向下归并):

    1. 找中点:使用快慢指针将链表一分为二。

    2. 递归排序:分别对左右链表递归调用 sortList

    3. 合并链表:调用 merge 合并两个已排序链表。

    ✅完整代码 

    class Solution:
        def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
            # base case:空或仅一个节点,返回自己
            if not head or not head.next:
                return head
    
            # 快慢指针找中点(slow为前半段尾部)
            slow, fast = head, head.next
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
    
            # 断链,分成左右两部分
            mid = slow.next
            slow.next = None
    
            # 递归排序左右子链表
            left = self.sortList(head)
            right = self.sortList(mid)
    
            # 合并两个有序链表
            return self.merge(left, right)
    
        def merge(self, l1: ListNode, l2: ListNode) -> ListNode:
            dummy = ListNode(0)
            tail = dummy
    
            # 合并两个有序链表(类似合并k个链表模板)
            while l1 and l2:
                if l1.val < l2.val:
                    tail.next = l1
                    l1 = l1.next
                else:
                    tail.next = l2
                    l2 = l2.next
                tail = tail.next
    
            # 将剩余部分接到尾部
            tail.next = l1 if l1 else l2
    
            return dummy.next
    

    ⏱️复杂度分析 

    类型复杂度说明
    时间复杂度O(n log n)每次划分为两半,递归深度为 log n,总共 O(n log n)
    空间复杂度O(log n)递归调用栈空间,非原地排序(迭代可优化到 O(1))

    🖼️图示理解

    链表 [4 → 2 → 1 → 3] 的归并排序过程:

    step1: [4,2,1,3] 
          ↓
    step2: [4,2] 和 [1,3]
          ↓
    step3: [4] 和 [2] → merge → [2,4]
            [1] 和 [3] → merge → [1,3]
          ↓
    step4: merge [2,4] 和 [1,3] → [1,2,3,4]
    

    🧱常见易错点总结 

    易错点说明
    快慢指针未正确断链slow.next = None 是断开关键
    未处理 head is None 情况base case 条件不能漏
    merge() 指针逻辑写错注意 tail 的移动与连接顺序
    使用快排/堆排不适用于链表,性能/实现都不友好

    🎯总结

    • 归并排序是链表排序的最优解法

    • 借助快慢指针找中点,递归合并实现排序。

     

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值