148. 排序链表

时间:2021-04-17
本文章向大家介绍148. 排序链表,主要包括148. 排序链表使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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

进阶:

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

示例 1:

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

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

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

提示:

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

解题思路:这道题说要用O(nlogn)的时间复杂度和常数级的空间复杂度来解决问题,时间复杂度就限定了只能用归并排序或者堆排序的方法,然后我一开始想的就是归并排序,但是一直有几个地方想不明白,那就是归并排序是要划分链表的,链表又不支持快速索引,应该怎样找到中间那个节点呢?另一个就是,归并排序递归调用的终点是每个待排序的链表内只有一个节点,也就是我们还要把整个链表断开,这个过程应该怎么处理呢?最后还是看了grandyang的题解,果然还是用这一套思路,划分链表用快慢指针来确定中间节点,然后把中间节点的next指针定为null,然后进行拼接,思路是一样的,就是代码写不出来。惨兮兮。

代码 t78 s66 java

class Solution {
    public ListNode sortList(ListNode head) {
        if(head==null || head.next==null) return head;
        ListNode cur = head, slow = head, fast = head;
        while(fast!=null && fast.next!=null){
            cur = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        cur.next = null;
        return merge(sortList(head), sortList(slow));
    }
    public ListNode merge(ListNode l1, ListNode l2){
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while(l1!=null && l2!=null){
            if(l1.val<l2.val){
                cur.next = l1;
                l1 = l1.next;
            }else{
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if(l1!=null) cur.next = l1;
        if(l2!=null) cur.next = l2;
        return dummy.next;
    }
}

参考资料
https://www.cyc2018.xyz/算法/基础/算法 - 排序.html
https://www.cnblogs.com/grandyang/p/4249905.html

原文地址:https://www.cnblogs.com/zhengxch/p/14670779.html