LongDz 的数字文墨提案

141. 环形链表

3 min

题目

141. 环形链表 简单

解法:快慢指针

思路

核心思想是快慢指针法(Floyd判圈算法)。快指针每次移动两步,慢指针每次移动一步,若存在环则两指针必会相遇。

正确性基于相对速度:当慢指针进入环时,快指针已在环内且领先若干节点。由于快指针相对慢指针每步靠近1个节点,在有限步内必然相遇。若链表无环,快指针将率先到达尾部终止循环。

  • Step 1: 初始化slow和fast指针均指向head
  • Step 2: 循环条件:fast非空且fast->next非空
  • Step 3: slow移动一步,fast移动两步
  • Step 4: 若slow==fast则返回true
  • Step 5: 循环结束未相遇则返回false

复杂度

  • 时间复杂度: O(n)O(n),最坏情况遍历整个链表(无环时快指针遍历n/2次)
  • 空间复杂度: O(1)O(1),仅使用两个指针的常量空间

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head==NULL || head->next==NULL){
            return false;
        }
        ListNode *slow = head;
        ListNode *fast = head;
        while(fast!=NULL && fast->next!=NULL){
            slow = slow->next;
            fast = fast->next->next;
            if(slow==fast){
                return true;
            }
        }
        return false;
    }
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head==NULL || head->next==NULL){
            return false;
        }
        ListNode *slow = head;
        ListNode *fast = head;
        while(fast!=NULL && fast->next!=NULL){
            slow = slow->next;
            fast = fast->next->next;
            if(slow==fast){
                return true;
            }
        }
        return false;
    }
};