【leetcode】148. 排序链表

75 阅读1分钟

leetcode-148.png

链表的归并排序

  • 分割链表: 使用快慢指针找到链表的中点,将链表分割成两个部分。
  • 递归排序: 对分割后的两个部分分别递归地进行排序。
  • 合并有序链表: 使用归并的方法将两个有序链表合并成一个有序链表。
var sortList = function (head) {
    // 终止递归的条件,当链表或者只有一个节点的时候,就是天然有序
    if (!head || !head.next) return head
    let slow = head, fast = head, pre = null
    // 找到中点
    while (fast && fast.next) {
        pre = slow
        slow = slow.next
        fast = fast.next.next
    }
    pre.next = null
    // 分解成最小的链表单位
    let left = sortList(head)
    let right = sortList(slow)
    // 进行合并
    return merge(left, right)
};

// 合并两个有序链表
var merge = function (l1, l2) {
    let dummy = new ListNode(-1)
    let current = dummy
    while (l1 && l2) {
        if (l1.val <= l2.val) {
            current.next = l1
            l1 = l1.next
        } else {
            current.next = l2
            l2 = l2.next
        }
        current = current.next
    }
    current.next = l1 || l2
    return dummy.next
}

⏱️ 时间 & 空间复杂度

  • 时间复杂度:O(n log n),每次将链表对半分,分 log n 层,每层最多遍历 n 个节点。
  • 空间复杂度:O(log n),递归栈的开销(不是原地排序,但符合题目对额外空间的要求)。