148. 排序链表(中)
题目
- 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
法一、冒泡排序
- 冒泡排序:两个for循环,i从头开始,j在i后一位开始,比较如果j小于i就交换,否则i往后移
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
i = head
j = head.next
if not head or head.next is None: # 如果链表为空或只有一个节点,直接返回链表本身
return []
p = ListNode(0)# 创建一个虚拟节点作为排序后链表的头节点
while i and i.next:
while j and j.next:
if j.val < i.val:
p.next, j.next = i.next, i
else:# 如果j大于等于i,则继续向后移动j节点
j = j.next
i = i.next
return p.next# 返回排序后链表的头节点
- 超时 :时间复杂度:O(n2);空间复杂度:O(1)
- 分析:
不适合的排序:基数排序(只适合非负数)、希尔排序(链表不支持随机访问,该排序涉及步长)、堆排序(树适合用顺序结构)
超时排序:冒泡排序、选择排序、插入排序、快速排序。
空间换时间:归并排序、计数排序、桶排序
法二、归并排序
class Solution:
def merge(self, left, right):
# 归并环节
dummy_head = ListNode(-1)#构造一个头节点
cur = dummy_head#用 cur 指向 dummy_head 用于遍历
while left and right:#比较两个链表头节点 left 和 right 的值大小。将较小的头节点加入到合并后的链表中。并向后移动该链表的头节点指针。
if left.val <= right.val:
cur.next = left
left = left.next
else:
cur.next = right
right = right.next
cur = cur.next
if left:
cur.next = left
elif right:
cur.next = right
return dummy_head.next
def mergeSort(self, head: ListNode):
# 分割环节
if not head or not head.next:
return head
# 快慢指针找到中心链节点
slow, fast = head, head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 断开左右链节点
left_head, right_head = head, slow.next
slow.next = None
# 归并操作
return self.merge(self.mergeSort(left_head), self.mergeSort(right_head))
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
return self.mergeSort(head)