Loading

Medium | LeetCode 148. 排序链表 | 归并排序(递归)

148. 排序链表

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

进阶:

  • 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

解题思路

方法一: 归并排序(递归)

public ListNode sortList(ListNode head) {
    return sortList(head, null);
}

/**
 * 排序[head, tail)这部分的链表, 这是一个左闭右开的链表
 * @param head 链表头部
 * @param tail 链表尾部
 * @return 排序后的链表
 */
public ListNode sortList(ListNode head, ListNode tail) {
    // 空链表直接返回
    if (head == null) {
        return head;
    }
    // 只有一个节点
    if (head.next == tail) {
        // 将next指针置位空
        head.next = null;
        return head;
    }
    // 快慢指针法找到链表的中间节点
    ListNode slow = head, fast = head;
    while (fast != tail) {
        // 慢指针每次走一步
        slow = slow.next;
        // 快指针每次走两步
        fast = fast.next;
        if (fast != tail) {
            fast = fast.next;
        }
    }
    // 将链表切成两块分别递归进行归并排序
    ListNode mid = slow;
    ListNode list1 = sortList(head, mid);
    ListNode list2 = sortList(mid, tail);
    return merge(list1, list2);
}

public ListNode merge(ListNode la, ListNode lb) {
    ListNode dumpHead = new ListNode();
    ListNode pre = dumpHead;
    ListNode pa = la, pb = lb;
    while (pa != null && pb != null) {
        if (pa.val <= pb.val) {
            pre.next = pa;
            pa = pa.next;
        } else {
            pre.next = pb;
            pb = pb.next;
        }
        pre = pre.next;
    }
    pre.next = (pa == null) ? pb : pa;
    return dumpHead.next;
}
posted @ 2021-06-20 19:35  反身而诚、  阅读(37)  评论(0编辑  收藏  举报