力扣第148题-排序链表

748 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情

前言

力扣第148题 排序链表 如下所示:

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

示例 1:

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

一、思路

题目很简短,与昨天的题目力扣第147题-对链表进行插入排序非常相似,都是将列表变为升序的排列

如果直接用昨天的代码 插入排序 是可以通过这一题的。此外还有一个非常朴素的思路如下所示:

  1. 遍历链表,收集所有元素
  2. 将收集到的元素按照升序排列
  3. 再次遍历链表,依次取排序好的元素值,修改每一个元素

像这样也是可以完成这一题的,但是这需要 O(n) 的空间来存储各节点,这就不能满足题目的进阶要求了。

image.png

归并排序

那要怎么做呢?既然要求 O(N*logN) 的时间复杂度和常数级空间复杂度,很容易就能想到使用 归并排序。归并排序的核心思想就是:先拆分,再合并

此处就以示例中的head = [4,2,1,3] 作为例子来展示,拆分的原则是按照链表的中间拆的,一直拆分到子链表中只有两个元素(一个元素是无需重新排序的,所以拆分到两个元素就可以了)。

  1. 拆分的过程

链表最终会拆分成如下的两个子链表

image.png

  1. 合并的过程

合并的过程就是先将子链表中的元素排好序,再将排好序的子链表合并,也就是合并两个升序排序的链表

image.png

综上所述,使用 归并排序 的步骤大致如下所示:

  1. 使用 递归 来拆分链表
  2. 将子链表按升序排列
  3. 多个子链表间,两两合并升序排列的链表

二、实现

实现代码

实现代码与思路中保持一致

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

public ListNode dfs(ListNode head, ListNode tail){
    if (head == null)
        return null;
    if (head.next == tail){
        head.next = null;
        return head;
    }
    // 从中间分割
    ListNode fast = head;
    ListNode slow = head;
    while (fast != tail){
        slow = slow.next;
        fast = fast.next;
        if (fast != tail)
            fast = fast.next;
    }
    ListNode listNode1 = dfs(head, slow);
    ListNode listNode2 = dfs(slow, tail );
    return mergeTwoLists(listNode1, listNode2);

}

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode ret = new ListNode();
    ListNode temp = ret;
    // 迭代
    while (l1 != null && l2 != null) {
        if (l1.val < l2.val) {
            temp.next = l1;
            l1 = l1.next;
        } else {
            temp.next =l2;
            l2 = l2.next;
        }
        temp = temp.next;
    }
    // 将未遍历完的列表归入结果
    if (l1 == null) {
        temp.next = l2;
    }
    if (l2 == null)
        temp.next = l1;
    return ret.next;
}

测试代码

public static void main(String[] args) {
    ListNode list = new ListNode(4, new ListNode(2, new ListNode(1, new ListNode(3))));
    ListNode ret = new Number148().sortList(list);
    System.out.println("test");
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~