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
二、思路分析
- 首先求得链表的长度length,然后将链表拆分成子链表进行合并。
- 排序链表使用归并的思想,第一次归并的长度为1,即一个一个节点有序合并,之后将归并长度翻倍,继续合并有序链表。
- 细节点在于对链表元素的操作。
三、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)