返回
路飞:程序员必刷力扣题:148. 排序合并
前端
2023-12-15 01:07:53
算法剖析
148. 排序合并
题目
给你一个头结点为 head
的无环单向表,请把它 原地 排序,并返回重新排序后的头结点。
示例:
示例 1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
提示:
- 题目保证 无环单向表 的性质。
- 排序后的单向表 必须 是 原地 排序,即在不创建新节点或使用额外空间的前提下进行排序。
算法实现
方法:归并排序
归并排序是一种经典的分治算法,它可以高效地对一个无序的单向表进行排序。其主要思想是:
- 将单向表一分为二,分别对这两个子表进行归并排序。
- 将排好序的子表合并起来,得到一个排好序的单向表。
步骤:
- 寻找中点: 使用快慢指针法找到单向表中的中点,慢指针每次走一步,快指针每次走两步。这样当快指针走到单向表的末尾时,慢指针刚好走到中点。
- 拆分单向表: 在中点处将单向表拆分成两个子表,
left
和right
。 - 归并排序子表: 对
left
和right
子表分别进行归并排序,得到两个排好序的子表。 - 合并子表: 将排好序的
left
和right
子表合并成一个排好序的单向表。合并过程中,从两个子表中比较取最小的节点,依次组成合并后的单向表。 - 返回结果: 返回合并好的单向表作为排好序后的结果。
代码实现(Python)
def sortList(head):
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
# 拆分单向表
mid = slow.next
slow.next = None
# 归并排序子表
left = sortList(head)
right = sortList(mid)
# 合并子表
return merge(left, right)
def merge(left, right):
dummy = ListNode(0)
curr = dummy
while left and right:
if left.val < right.val:
curr.next = left
left = left.next
else:
curr.next = right
right = right.next
curr = curr.next
curr.next = left or right
return dummy.next
复杂度分析
时间复杂度: O(n log n)
空间复杂度: O(1)
优化技巧
- 避免不必要复制: 在合并子表时,可以通过指针操作直接修改原单向表,避免创建新的节点。
- 使用栈而不是显式拆分: 使用栈来存储单向表的拆分点,可以简化拆分和合并的代码。
应用场景
该算法在以下场景中非常有用:
- 对大型单向表进行 原地 排序。
- 在内存受限的环境中对数据进行排序。
- 作为一种通用的排序算法,适用于各种数据结构。
结语
掌握排序合并算法对于程序员来说非常重要。它是一种高效的原地排序算法,在实际应用中有着举足轻重的作用。通过对算法的深入理解和优化,程序员可以在面试和编码实践中游刃有余。