春招打卡|排序链表

97 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述

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

示例 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

二、思路分析

  1. 首先求得链表的长度length,然后将链表拆分成子链表进行合并。
  2. 排序链表使用归并的思想,第一次归并的长度为1,即一个一个节点有序合并,之后将归并长度翻倍,继续合并有序链表。
  3. 细节点在于对链表元素的操作。

三、AC 代码

func sortList(head *ListNode) *ListNode {
    if head == nil {
        return nil
    }
    length := 0
    for cur := head;cur != nil ;cur = cur.Next {
        length++
    }
    dummynode := &ListNode{Next:head}
    for sublen := 1;sublen < length; sublen = sublen * 2 {
        pre ,cur := dummynode,dummynode.Next
        for cur != nil {
            head1 := cur
            for i := 1;i<sublen && cur.Next != nil ;i++ {
                cur = cur.Next
            }
            head2 := cur.Next
            cur.Next = nil
            cur = head2 
            for i := 1;i<sublen && cur != nil && cur.Next != nil;i++ {
                cur = cur.Next
            }
            var next *ListNode
            if cur != nil {
                next = cur.Next
                cur.Next = nil 
            }
            pre.Next = merge(head1,head2)
            for pre.Next != nil {
                pre = pre.Next
            }
            cur = next
        }
    }
    return dummynode.Next
}

func merge(head1 *ListNode,head2 *ListNode) *ListNode {
    dummynode := &ListNode{}
    pre := dummynode
    for head1 != nil && head2 != nil {
        if head1.Val < head2.Val {
            pre.Next = head1
            head1 = head1.Next
        }else{
            pre.Next = head2
            head2 = head2.Next
        }
        pre = pre.Next
    }
    if head1 == nil {
        pre.Next = head2
    }
    if head2 == nil {
        pre.Next =  head1
    }
    return dummynode.Next
}

四、总结

时间复杂度为O(nlogn),空间复杂度为O(1)