[路飞]_148. 排序链表

113 阅读1分钟

题目路径

题目描述

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

image.png

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

示例 2:

image.png

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

示例 3:

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

解题思路1-快速排序

  • 先找到当前链表的中间值,把链表分割成两部分,小于中间值的放到h1,大于中间值的放到h2.
  • 递归上述步骤,返回排序好的h1和h2
  • 将h1链接到h2后面,返回h1即可

代码1

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;
    while(p) {
        q = p.next;
        l = Math.min(p.val, l);
        r = Math.max(p.val, r);
        p = q;
    }
    // 当head只有一个值的时候,返回head
    if(l == r) return head;
    mid = (l + r) / 2; // 找到中间值
    p = head;
    while(p) {
        q = p.next;
        if(p.val <= mid) {
            p.next = h1;
            h1 = p;
        } else {
            p.next = h2;
            h2 = p;
        }
        p = q;
    }
    h1 = sortList(h1);
    h2 = sortList(h2);
    p = h1;
    // 循环p.next
    while(p.next) {
        p = p.next;
    }
    p.next = h2;
    return h1;
}

解题思路2

  • 切断所有的链表
  • 用sort对切断的链表做排序
  • 链接链表

代码2

var sortList = function(head) {
    // 特判
    if(head == null) return head;
    let p = head, q;
    let s = [];
    while(p) {
        q = p.next;
        p.next = null;
        s.push(p);
        p = q;
    }
    s = s.sort((a, b) => a.val - b.val);
    for(let i = 0; i < s.length - 1; i++){
        s[i].next = s[i + 1];
    }
    return s[0];
}

解题思路3-归并排序

  • 把链表一分为二,先处理左边,然后处理右边
  • 然后分别处理左右两边

代码3

var sortList = function(head) {
    let n = 0;
    let p = head;
    while(p) p = p.next, n += 1;
    return mergeSort(head, n);
}

var mergeSort = function(head, n) {
    if(head == null || head.next == null) return head;
    let l = n >> 2, r = n - l;
    let lp = head, rp = lp, p;
    for(let i = 1; i < l; i++){
        rp = rp.next;
    };
    p = rp, rp = rp.next;
    p.next = null;
    lp = mergeSort(lp, l);
    rp = mergeSort(rp, r);
    let ret = new ListNode();
    p = ret;
    while(lp || rp) {
        if((rp == null) || (lp && lp.val <= rp.val)){
            p.next = lp;
            lp = lp.next;
            p = p.next;
        } else {
            p.next = rp;
            rp = rp.next;
            p = p.next;
        }
    }
    return ret.next;
}