返回

环形链表——刷题打卡:巧妙运用指针技巧

前端

在编程的世界里,链表是一种常见的数据结构,它由一组节点组成,每个节点都包含数据和指向下一个节点的指针。环形链表是一种特殊类型的链表,其中最后一个节点的指针指向链表中的第一个节点,形成一个闭合的环。环形链表的判定是算法面试中经常考察的题目之一,掌握其判定技巧可以帮助我们解决更复杂的算法问题。

1. 快慢指针法:追逐竞赛

快慢指针法是一种判定环形链表的经典方法。该方法利用了链表的循环性质,即如果链表中存在环,那么从链表中的任意位置出发,沿着next指针移动,最终都会回到起始位置。

快慢指针法的核心思想是使用两个指针,一个称为快指针,另一个称为慢指针。快指针每次移动两个节点,而慢指针每次移动一个节点。如果链表中存在环,那么快指针最终会追上慢指针,相遇点就是环的入口节点。

def has_cycle(head):
  """
  判定链表中是否存在环。

  参数:
    head: 链表的头节点。

  返回:
    如果链表中存在环,则返回 True;否则,返回 False。
  """

  # 如果链表为空或只有一个节点,则不存在环。
  if head is None or head.next is None:
    return False

  # 初始化快指针和慢指针。
  slow = head
  fast = head.next

  # 循环遍历链表,直到快指针追上慢指针或到达链表尾部。
  while slow != fast and fast is not None and fast.next is not None:
    # 移动快指针和慢指针。
    slow = slow.next
    fast = fast.next.next

  # 如果快指针和慢指针相遇,则链表中存在环。
  return slow == fast

2. 哈希表法:标记节点

哈希表法也是一种判定环形链表的方法。该方法利用了哈希表的数据结构,将链表中的节点作为键值对存储在哈希表中。如果某个节点已经存储在哈希表中,那么链表中就存在环,环的入口节点就是该节点。

def has_cycle(head):
  """
  判定链表中是否存在环。

  参数:
    head: 链表的头节点。

  返回:
    如果链表中存在环,则返回 True;否则,返回 False。
  """

  # 初始化哈希表。
  hash_table = set()

  # 循环遍历链表,将每个节点存储在哈希表中。
  while head is not None:
    # 如果当前节点已经存储在哈希表中,则链表中存在环。
    if head in hash_table:
      return True

    # 将当前节点存储在哈希表中。
    hash_table.add(head)

    # 移动到下一个节点。
    head = head.next

  # 如果遍历完整个链表,没有发现环,则链表中不存在环。
  return False

3. 弗洛伊德循环检测法:巧妙的步调

弗洛伊德循环检测法是一种基于快慢指针法的环形链表判定方法。该方法利用了链表的循环性质,即如果链表中存在环,那么从链表中的任意位置出发,沿着next指针移动,最终都会回到起始位置。

弗洛伊德循环检测法与快慢指针法的区别在于,它只使用了一个指针,称为乌龟指针。乌龟指针每次移动一步,直到它遇到另一个节点或到达链表尾部。如果乌龟指针遇到了另一个节点,那么链表中存在环,环的入口节点就是该节点。

def has_cycle(head):
  """
  判定链表中是否存在环。

  参数:
    head: 链表的头节点。

  返回:
    如果链表中存在环,则返回 True;否则,返回 False。
  """

  # 如果链表为空或只有一个节点,则不存在环。
  if head is None or head.next is None:
    return False

  # 初始化乌龟指针。
  slow = head

  # 循环遍历链表,直到乌龟指针遇到另一个节点或到达链表尾部。
  while slow is not None:
    # 移动乌龟指针。
    slow = slow.next

    # 如果乌龟指针遇到另一个节点,则链表中存在环。
    if slow in hash_table:
      return True

    # 将当前节点存储在哈希表中。
    hash_table.add(slow)

  # 如果遍历完整个链表,没有发现环,则链表中不存在环。
  return False

结语

环形链表的判定是算法面试中经常考察的题目之一,掌握其判定技巧可以帮助我们解决更复杂的算法问题。快慢指针法、哈希表法和弗洛伊德循环检测法都是判定环形链表的常用方法,每种方法都有其优缺点。在实际应用中,我们可以根据具体情况选择合适的方法来判定环形链表。