返回

快指针疾如风,慢指针稳如山:巧用双指针,判断链表环中环

IOS

快慢指针判断链表是否有环:一次过关的面试技巧

引言

在算法面试中,链表环检测问题是考察应聘者对数据结构和算法理解程度的经典题目之一。本文将深入浅出地介绍如何使用快慢指针技术高效地判断单向链表中是否存在环,帮助你一次过关算法面试。

快慢指针的原理

快慢指针算法基于这样一个事实:如果链表中存在环,那么无论链表有多长,最终都会有时刻,一个指针(快指针)会追上另一个指针(慢指针)。这是因为快指针每次移动两步,而慢指针每次只移动一步。因此,如果链表中有环,快指针必定会绕着环圈多次循环,最终追上慢指针。

算法步骤

  1. 初始化两个指针 :快指针(fast) 和慢指针(slow),都指向链表的头部。
  2. 迭代链表
    • 快指针每次移动两步:fast = fast->next->next
    • 慢指针每次移动一步:slow = slow->next
  3. 判断快慢指针相遇
    • 如果快指针或其后继为 null,则链表中没有环。
    • 如果快指针追上慢指针(即 fast == slow),则链表中存在环。

优势

快慢指针算法具有以下优势:

  • 时间复杂度:O(n) ,其中 n 是链表中的节点数。
  • 空间复杂度:O(1) ,因为算法只使用了常数个指针。
  • 简单易懂 ,易于实现和理解。

注意要点

虽然快慢指针算法非常有效,但仍需注意以下几点:

  • 非循环链表 :对于非循环链表,快指针最终将指向 null,此时算法可以立即终止。
  • 环的入口点 :该算法仅能检测出链表中是否存在环,但不能确定环的入口点。
  • 指向头的环 :如果环的入口点为链表头部,则快指针会在第一轮迭代后就追上慢指针。

示例代码

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

    Args:
        head (ListNode): 链表头部。

    Returns:
        bool: 是否存在环。
    """
    if not head or not head.next:
        return False

    fast = head
    slow = head

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

        if fast == slow:
            return True

    return False

总结

快慢指针算法是一种高效实用的技术,可用于判断单向链表中是否存在环。理解其原理、优势和注意事项,将帮助你轻松应对算法面试中的环检测问题。