链表操作大全:LeetCode链表反转、环检测与合并模板
【免费下载链接】leetcodepython 数据结构与算法 leetcode 算法题与书籍 刷算法全靠套路与总结!Crack LeetCode, not only how, but also why.项目地址: https://gitcode.com/gh_mirrors/leetcode82/leetcode
在数据结构与算法的学习中,链表是一种基础且重要的数据结构,广泛应用于各类算法题和实际工程中。本文将围绕LeetCode中常见的链表操作,详细介绍链表的反转、环检测与合并等核心模板,帮助新手快速掌握链表操作的精髓。
链表基础与核心结构
链表是由一系列节点组成的数据结构,每个节点包含数据域和指针域。在Python中,链表节点通常定义为:
class ListNode: def __init__(self, x): self.val = x self.next = None链表的优势在于插入和删除操作的高效性,尤其是在链表头部或中间位置。但相比数组,链表的随机访问性能较差,需要从头节点开始遍历。
算法思维导图:展示了链表在算法体系中的位置及相关知识点
一、链表反转:迭代与递归实现
链表反转是LeetCode中最经典的问题之一,主要有迭代和递归两种实现方式。
1. 迭代法反转链表
迭代法通过三个指针(prev、cur、next)的移动来实现链表的反转,时间复杂度O(n),空间复杂度O(1)。
def reverse_iteratively(head: ListNode) -> ListNode: prev, cur = None, head while cur: cur.next, cur, prev = prev, cur.next, cur return prev核心思路:
- 初始化prev为None,cur为头节点
- 遍历链表,每次将cur的next指向prev
- 移动prev和cur指针,直到cur为None
- prev即为反转后的头节点
2. 递归法反转链表
递归法通过将大问题分解为小问题来实现,代码简洁但理解难度稍高。
def reverse_recursively(head: ListNode) -> ListNode: def recursive(cur, pre=None): if not cur: return pre pre, cur.next = cur.next, pre return recursive(pre, cur) return recursive(head)应用场景:LeetCode 206.反转链表、92.反转链表II等
二、环检测:Floyd判圈算法
判断链表中是否存在环以及找到环的入口,是链表操作中的另一个经典问题。Floyd判圈算法(快慢指针法)是解决此类问题的高效方法。
def detectCycle(head): slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: # 存在环 break else: # 无环 return None # 找环入口 while head != slow: slow = slow.next head = head.next return head算法原理:
- 快指针每次走两步,慢指针每次走一步
- 若存在环,两指针必定相遇
- 相遇后,将慢指针移回头节点,两指针同速前进,再次相遇点即为环入口
时间复杂度:O(n),空间复杂度:O(1)
三、链表合并:有序链表的合并
合并两个有序链表是链表操作中的常见需求,可通过迭代或递归实现。
1. 迭代法合并
def mergeTwoLists1(l1: ListNode, l2: ListNode) -> ListNode: curr = dummy = ListNode(0) while l1 and l2: if l1.val < l2.val: curr.next = l1 l1 = l1.next else: curr.next = l2 l2 = l2.next curr = curr.next curr.next = l1 or l2 # 处理剩余节点 return dummy.next2. 递归法合并
def mergeTwoLists2(a, b): if a and b: if a.val > b.val: a, b = b, a a.next = mergeTwoLists2(a.next, b) return a or b应用场景:LeetCode 21.合并两个有序链表、23.合并K个升序链表
四、实战技巧与常见问题
1. 哑节点(Dummy Node)的使用
在头节点可能发生变化的场景(如合并、删除头节点),使用哑节点可以简化边界条件处理:
def dummy_node_assist(self, head): dummy = ListNode(0) cur = dummy.next = head # 处理逻辑... return dummy.next2. K个一组翻转链表
LeetCode 25题要求每K个节点一组翻转链表,可结合迭代反转和哑节点实现:
def reverseKGroup1(head, k): dummy = jump = ListNode(0) dummy.next = l = r = head while True: count = 0 while r and count < k: r = r.next count += 1 if count == k: pre, cur = r, l for _ in range(k): cur.next, cur, pre = pre, cur.next, cur jump.next, jump, l = pre, l, r else: return dummy.next3. 链表操作的时间复杂度分析
排序算法性能对比图:链表相关操作的时间复杂度分析
常见链表操作的时间复杂度:
- 访问节点:O(n)
- 插入/删除节点:O(1)(已知前驱节点)
- 反转链表:O(n)
- 环检测:O(n)
- 合并两个有序链表:O(m+n)
五、总结与资源推荐
链表操作是算法面试的基础,掌握本文介绍的反转、环检测和合并模板,能够解决大多数链表相关问题。更多实战案例和详细代码可参考:
- 算法模板:algorithm_templates/linked_list/linked_list.py
- 示例代码:algorithm_templates/linked_list/linked_list_examples.py
通过大量练习,熟悉链表的指针操作和边界处理,能够显著提升解决复杂链表问题的能力。记住,刷算法全靠套路与总结,掌握这些模板将为你的算法之旅打下坚实基础!
【免费下载链接】leetcodepython 数据结构与算法 leetcode 算法题与书籍 刷算法全靠套路与总结!Crack LeetCode, not only how, but also why.项目地址: https://gitcode.com/gh_mirrors/leetcode82/leetcode
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考