返回

快慢指针打造两条线,环形链表抓住尾:LeetCode经典挑战之环形链表II

前端

前言:环形链表简介

环形链表是一种特殊的数据结构,它的特点是最后一个节点指向第一个节点,从而形成一个环。这种数据结构在实际开发中经常用到,比如音乐播放器中的歌曲列表、浏览器中的历史记录等。

快慢指针思想探秘

理解环形链表,少不了要认识一个关键的思想——快慢指针。快慢指针是一种经典的算法思想,它利用两个指针同时遍历链表,一个指针的速度较快,另一个指针的速度较慢。当快指针追上慢指针时,说明链表中存在环。

举个例子:

假设我们有一个环形链表,包含5个节点。快指针和慢指针从头节点同时出发,快指针每次移动两步,而慢指针每次移动一步。

初始状态:

快指针指向头节点A
慢指针指向头节点A

第一次移动:

快指针指向C
慢指针指向B

第二次移动:

快指针指向E
慢指针指向C

第三次移动:

快指针追上了慢指针

此时,我们可以确定链表中存在环。

代码实现:

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

    Args:
        head: 链表的头节点。

    Returns:
        True if there is a cycle in the linked list, False otherwise.
    """
    # 设置快慢指针
    slow = head
    fast = head

    # 循环遍历链表,直到快指针追上慢指针或到达链表末尾
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

        if slow == fast:
            return True

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

LeetCode 142:环形链表II

LeetCode 142 环形链表II 是一个经典的题目,它要求我们在不修改链表的情况下,找到环形链表的入口节点。

算法思路:

  1. 使用快慢指针找到环形链表中的相遇点。
  2. 设置一个新的指针,从头节点出发,与相遇点同时向后移动。
  3. 当两个指针相遇时,就是环形链表的入口节点。

代码实现:

def detect_cycle(head):
    """
    找到环形链表的入口节点。

    Args:
        head: 链表的头节点。

    Returns:
        The entrance node of the cycle, or None if there is no cycle.
    """
    # 使用快慢指针找到环形链表中的相遇点
    slow = head
    fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

        if slow == fast:
            break

    # 如果链表中不存在环,直接返回None
    if not fast or not fast.next:
        return None

    # 设置一个新的指针,从头节点出发,与相遇点同时向后移动
    ptr1 = head
    ptr2 = slow

    # 当两个指针相遇时,就是环形链表的入口节点
    while ptr1 != ptr2:
        ptr1 = ptr1.next
        ptr2 = ptr2.next

    # 返回环形链表的入口节点
    return ptr1

结语

环形链表是数据结构中一个重要的知识点,它在实际开发中经常用到。理解环形链表的结构和算法,对于算法工程师来说非常重要。快慢指针的思想,也是算法学习中经常遇到的思想,掌握这个思想,可以帮助你解决很多复杂的问题。