[路飞]_leetcode_148. 排序链表

649 阅读1分钟

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

示例 1:

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

示例 2:

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

示例 3:

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

解题思路

这一题我们可以用快排算法 partition 的思想来做。 首先快排算法需要一个基准值来将每个数分成大于基准值或小于等于基准值的两个部分,然后递归来区分,最终组成数组。 那么我们也可以通过快排算法的思想,将链表分为两个部分。

  1. 遍历一次链表获取链表中的最大值和最小值,来取 mid 基准值
  2. 将小于等于基准值的节点放到h1链表, 将大于基准值的节点放到h2链表
  3. 将h1, h2链表继续细分下去
  4. 将排序好的h1和h2链表合并

代码

var sortList = function(head) {
    if (head == null) return head
    let l = head.val, r = head.val, mid
    let p = head, q, h1 = null, h2 = null
    // 首先获取最大值和最小值,来取 mid 基准值
    while(p) {
        l = Math.min(l, p.val)
        r = Math.max(r, p.val)
        p = p.next
    }
    if (l == r) return head
    mid = (l + r) >> 1
    p = head
    // 遍历链表
    while (p) {
        q = p.next
        // 将小于等于基准值的节点放到h1链表
        if (p.val <= mid) {
            p.next = h1
            h1 = p
        } else { // 将大于基准值的节点放到h2链表
            p.next = h2
            h2 = p
        }
        p = q
    }
    // 循环上述步骤
    h1 = sortList(h1)
    h2 = sortList(h2)
    // 将h1链表与h2链表合并
    p = h1
    while(p.next) p = p.next
    p.next = h2
    return h1
};