返回

算法成长之路一:环形链表的征服之路

前端







**引言** 

欢迎来到我的算法成长之路!在这个系列文章中,我将分享我在刷题过程中的心得体会、算法思路和代码实现。每一篇都会聚焦一个特定的算法或数据结构,旨在帮助大家循序渐进地提升算法能力。

**初识环形链表** 

环形链表是一种特殊类型的链表,其中最后一个结点的next域指向链表中的某个已存在结点,形成一个闭合的环路。与普通链表不同,环形链表没有显式的表尾结点。

**LeetCode 141:环形链表** 

LeetCode 141题要求判断一个给定的链表是否包含环路。以下是这道题的题目

给定一个链表,判断链表中是否有环。

为了表示给定的链表,我们使用整数数组 A。每个元素 A[i] 代表链表中的第 i 个结点的值。如果链表中有环,则 A[i] 的值可以重复出现。链表中的所有结点都保证是 0 <= A[i] <= 1000。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个结点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个结点。

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。


**算法思路** 

为了判断一个链表中是否存在环路,我们可以使用两种常见的算法:

**1. 双指针法** 

这种方法使用两个指针,一个称为快指针,另一个称为慢指针。快指针每次前进两步,而慢指针每次前进一步。如果链表中有环,快指针最终会追上慢指针,表明存在环路。

**2. 哈希表法** 

这种方法使用一个哈希表来存储已访问过的结点。当遍历链表时,如果遇到一个已经存在于哈希表中的结点,则说明存在环路。

**代码实现** 

以下是用Python实现的双指针法的代码:

```python
def has_cycle(head):
  """
  判断链表中是否存在环路。

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

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

  # 定义快慢指针。
  fast = head
  slow = head

  # 遍历链表。
  while fast and fast.next:
    # 快指针前进两步。
    fast = fast.next.next
    # 慢指针前进一步。
    slow = slow.next

    # 如果快慢指针相遇,说明存在环路。
    if fast == slow:
      return True

  # 如果快指针到达链表末尾,说明不存在环路。
  return False

代码优化

双指针法的时间复杂度为O(n),其中n为链表的长度。为了进一步优化性能,我们可以使用弗洛伊德循环检测算法 。该算法的思想是:如果链表中有环,那么快慢指针最终会在环内相遇。相遇点到环入口点的距离等于环的长度。因此,我们可以使用快慢指针再次遍历链表,并计算快慢指针相遇点到链表头结点的距离。如果该距离等于环的长度,则说明存在环路。

弗洛伊德循环检测算法 的代码实现如下:

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

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

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

  # 定义快慢指针。
  fast = head
  slow = head

  # 遍历链表,直到快慢指针相遇。
  while fast and fast.next:
    # 快指针前进两步。
    fast = fast.next.next
    # 慢指针前进一步。
    slow = slow.next

    # 如果快慢指针相遇,说明存在环路。
    if fast == slow:
      break

  # 如果快慢指针未相遇,说明不存在环路。
  if not fast or not fast.next:
    return False

  # 计算快慢指针相遇点到链表头结点的距离。
  distance = 0
  temp = head
  while temp != slow:
    temp = temp.next
    distance += 1

  # 计算环的长度。
  length = 0
  temp = slow.next
  while temp != slow:
    temp = temp.next
    length += 1

  # 如果相遇点到头结点的距离等于环的长度,说明存在环路。
  return distance == length

结语

通过本文,我们深入探讨了环形链表及其循环检测算法。双指针法和弗洛伊德循环检测算法都是高效且实用的方法。通过对这些算法的理解和实践,我们可以不断提升我们的算法能力,为解决更复杂的算法问题做好准备。