给你链表的头结点 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
思路:
-1.断链
-2.合并
-3.循环
python
# 0148.排序链表
"""
知识点1:归并排序的整体思想
知识点2:找到一个链表的中间节点的方法
知识点3:合并两个已排好序的链表为一个新的有序链表
"""
# 参考:https://leetcode-cn.com/problems/sort-list/solution/pai-xu-lian-biao-di-gui-die-dai-xiang-jie-by-cherr/
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
class Solution:
def sortList1(self, head: ListNode) -> ListNode:
"""
迭代,时间O(nlogn), 空间O(1)
:param head:
:return:
"""
length = self.getLength(head)
dummy = ListNode(-1)
dummy.next = head
step = 1
while step < length:
# 每次变换步长, pre和cur指针初始化在表头
pre, cur = dummy, dummy.next
while cur:
h1 = cur # 第一部分头,第二次循环之后,cur为剩余部分头,不断往后把链表按照步长step分成一块一块...
h2 = self.split(h1, step) # 第二部分头
cur = self.split(h2, step) # 剩余部分头
temp = self.merge(h1, h2) # 一二部分合并
pre.next = temp # 前面部分与排序好的连接
while pre.next:
pre = pre.next # pre移动到排序好部分的末尾
step = step * 2
return dummy.next
def sortList(self, head: ListNode) -> ListNode:
"""
递归法,时间O(nlogn), 空间O(logn)
:param head:
:return:
"""
if head is None or head.next is None:
return head
slow, fast = head, head.next
# 断链
while fast != None and fast.next != None:
slow = slow.next
fast = fast.next.next
rightHead = slow.next
slow.next = None
# 递归
left = self.sortList(head)
right = self.sortList(rightHead)
# 合并
return self.merge(left, right)
def merge(self, h1, h2: ListNode) -> ListNode:
dummy = ListNode(-1)
p = dummy
while h1 != None and h2 != None:
if h1.val < h2.val:
p.next = h1
h1 = h1.next
else:
p.next = h2
h2 = h2.next
p = p.next
p.next = h1 or h2
return dummy.next
def getLength(self, head: ListNode) -> int:
cnt = 0
while head:
cnt += 1
head = head.next
return cnt
def split(self, head: ListNode, step: int) -> ListNode :
# 断链操作
if head == None:
return head
cur = head
for i in range(1, step):
if cur.next != None:
cur = cur.next
right = cur.next
cur.next = None # 以cur为界断开原链
# 返回右链链头
return right
golang
// 迭代
func sortList1(head *ListNode) *ListNode {
length := getLength(head)
dummy := &ListNode{}
dummy.Next = head
for step := 1; step < length; step = step * 2 {
pre, cur := dummy, dummy.Next
for cur != nil {
h1 := cur
h2 := split(h1, step)
cur = split(h2, step)
temp := merge(h1, h2)
pre.Next = temp
for pre.Next != nil {
pre = pre.Next
}
}
}
return dummy.Next
}
func getLength(head *ListNode) int {
cnt := 0
cur := head
for cur != nil {
cnt++
cur = cur.Next
}
return cnt
}
func split(head *ListNode, step int) *ListNode {
if head == nil {
return head
}
cur := head
for i := 1; i < step; i++ {
if cur.Next != nil {
cur = cur.Next
}
}
right := cur.Next
cur.Next = nil
return right
}
// 递归 leetcode提示初始时间限制
func sortList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
// 断链
slow, fast := head, head.Next
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next
}
rightHead := slow.Next
slow.Next = nil
// 递归
left := sortList(head)
right := sortList(rightHead)
return merge(left, right)
}
func merge(h1, h2 *ListNode) *ListNode {
dummy := &ListNode{}
p := dummy
for h1 != nil && h2 != nil {
if h1.Val < h2.Val {
p.Next = h1
h1 = h1.Next
} else {
p.Next = h2
h2 = h2.Next
}
p = p.Next
}
if h1 != nil {
p.Next = h1
} else {
p.Next = h2
}
return dummy.Next
}