排序链表
本文最后更新于32 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

🔗 排序链表

题目来源:148. 排序链表 – 力扣(LeetCode)

📌 题目描述

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

要求:

  • 时间复杂度:O(n log n)
  • 空间复杂度:O(log n)(递归栈空间,符合“常数级额外空间”的宽松解释)
  • 不能转换成数组排序再重建链表(考察链表原地操作能力)

✅ 示例解析

示例 1:

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

示例 2:

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

示例 3:

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

⚠️ 提示

  • 链表中节点数目范围:[0, 5 * 10⁴]
  • Node.val 范围:[-10⁵, 10⁵]

💡 解法:自顶向下归并排序(Top-Down Merge Sort)—— O(n log n) 时间,O(log n) 空间

class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }

        ListNode mid = middleNode(head);
        ListNode rightHead = mid.next;
        mid.next = null;

        ListNode left = sortList(head);
        ListNode right = sortList(rightHead);

        return merge(left, right);
    }

    private ListNode middleNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head.next;

        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }

        return slow;
    }

    private ListNode merge(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1);
        ListNode curr = dummy;

        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                curr.next = l1;
                l1 = l1.next;
            } else {
                curr.next = l2;
                l2 = l2.next;
            }
            curr = curr.next;
        }

        curr.next = l1 != null ? l1 : l2;
        return dummy.next;
    }
}

📊 复杂度分析

  • 时间复杂度:O(n log n) ✅
    • 分:每次找中点 O(n),共 log n 层 → 总 O(n log n)
    • 治:每层合并总长为 n,共 log n 层 → 总 O(n log n)
  • 空间复杂度:O(log n)
    • 递归调用栈深度为 log n(链表长度每次减半)
    • 符合题目“常数级额外空间”的宽松要求(对比数组归并的 O(n))

⚠️ 注:若要求 严格 O(1) 空间,需使用“自底向上归并排序”,但代码复杂,面试中本解法已足够。

🧩 解题思路

核心思想:分治法(Divide and Conquer) + 归并排序

  1. 递归终止条件:
    • head == null 或 head.next == null → 无需排序,直接返回。
  2. 分 —— 找中点 & 断链:
    • 使用快慢指针找中点(slow 和 fast)。
    • fast = head.next → 保证偶数节点时,slow 停在左中点(如 4 个节点停在第 2 个)。
    • midNode.next = null → 将链表从中间断开,分成 head 到 midNode 和 rightHead 开头的两部分。
  3. 治 —— 递归排序:
    • left = sortList(head) → 递归排序左半部分
    • right = sortList(rightHead) → 递归排序右半部分
  4. 合 —— 合并有序链表:
    • 调用 mergeTwoLists(left, right),将两个有序链表合并成一个有序链表。
    • 使用哨兵节点 dummy 简化头节点处理。
  5. 返回合并结果。
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇