初探 LeetCode 147:对链表进行插入排序的 Python 巧解
2023-10-16 08:38:04
导言
算法竞赛的殿堂里,LeetCode 147 是一道经典题,它考验着算法爱好者们对链表数据结构的理解和运用能力。这道题要求我们对一个无序链表进行插入排序,按照从小到大的顺序排列元素。本篇文章将带你领略 Python 语言下的优雅解法,为你打开算法思维的另一扇窗。
算法流程
插入排序算法的精髓在于将待排序的元素逐个插入到已排序序列中。对于链表结构,插入过程需要格外谨慎,以维护链表的连贯性。算法流程如下:
-
初始化 :设置头指针(Head)和当前指针(Current)。Head 指向链表头,Current 指向待排序元素。
-
循环遍历 :对于每一个待排序元素(Current),执行以下操作:
- 将 Current 指向待插入元素。
- 比较 Current 与其前驱元素(Current.prev),直到找到合适的位置。
- 将 Current 插入到前驱元素之后。
-
更新指针 :将 Current 指向待插入元素的下一个元素。
-
循环结束 :当所有元素都已排序,算法终止,返回头指针。
Python 实现
def insertion_sort_list(head):
"""
对链表进行插入排序。
参数:
head:链表头节点
返回:
排序后的链表头节点
"""
if not head or not head.next:
return head
dummy = ListNode(0)
dummy.next = head
current = head
while current and current.next:
if current.val <= current.next.val:
current = current.next
else:
prev = dummy
while prev.next.val < current.next.val:
prev = prev.next
nxt = current.next
current.next = nxt.next
nxt.next = prev.next
prev.next = nxt
return dummy.next
代码解读
-
初始化 :创建哨兵节点 dummy,它指向链表头。这样,算法可以处理空链表和只有一个元素的链表。
-
遍历链表 :使用 current 指针遍历链表。
-
比较元素 :如果 current.val <= current.next.val,说明元素已经处于正确的位置,继续遍历。否则,需要插入排序。
-
查找插入点 :使用 prev 指针遍历已排序链表,找到插入点(即 prev.next.val < current.next.val)。
-
插入元素 :将 current.next 元素插入到 prev 和 prev.next 之间。
-
更新指针 :将 current 指向 current.next。
-
返回结果 :返回哨兵节点 dummy 的 next 指向的节点,即排序后的链表头。
优势和限制
优势 :
- 简单易懂,代码清晰易读。
- 时间复杂度为 O(n^2),适用于规模较小的链表。
- 空间复杂度为 O(1),不需要额外的空间。
限制 :
- 对于大型链表,时间复杂度较高。
- 对于特殊情况(如链表为空或只有一个元素),需要特殊处理。
结语
LeetCode 147 是一道经典算法题,它考验着对链表结构和插入排序算法的理解。通过 Python 的简洁实现,我们可以领会算法的精髓和优势。希望这篇文章能够激发你的算法热情,助你踏上算法竞赛的征途。
参考