【路飞】算法与数据结构-排序链表

72 阅读1分钟

不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。

LeetCode:原题地址

题目要求

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

示例 1:

sort_list_1.jpg

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

示例 2:

sort_list_2.jpg

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

示例 3:

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

提示:

  • 链表中节点的数目在范围 [0, 5 * 104] 内
  • -105 <= Node.val <= 105

思路

用归并排序的思路,先不断分割,知道每个子区间只有一个节点位置,然后开始合并

const merge = (head1, head2) => {
    const dummyHead = new ListNode(0);
    let temp = dummyHead, temp1 = head1, temp2 = head2;
    while (temp1 !== null && temp2 !== null) {//合并子区间 小的节点先连
        if (temp1.val <= temp2.val) {
            temp.next = temp1;
            temp1 = temp1.next;
        } else {
            temp.next = temp2;
            temp2 = temp2.next;
        }
        temp = temp.next;
    }
    if (temp1 !== null) {//两条链表还有节点没合并完,直接合并过来
        temp.next = temp1;
    } else if (temp2 !== null) {
        temp.next = temp2;
    }
    return dummyHead.next;
}

const toSortList = (head, tail) => {
    if (head === null) {//极端情况
        return head;
    }
    if (head.next === tail) {//分割到只剩一个节点
        head.next = null;
        return head;
    }
    let slow = head, fast = head;
    while (fast !== tail) {//的到中间节点
        slow = slow.next;
        fast = fast.next;
        if (fast !== tail) {
            fast = fast.next;
        }
    }
    const mid = slow;
    return merge(toSortList(head, mid), toSortList(mid, tail));//分割区间 递归合并
}

var sortList = function(head) {
    return toSortList(head, null);
};