Leetcode 141. 环形链表(简单) 142. 环形链表II(简单) 快慢指针判断环形链表

141. 环形链表(简单)

题目:

判定链表中是否含有环

思路:

用两个指针,一个跑得快,一个跑得慢。如果不含有环,跑得快的那个指针最终会遇到 null,说明链表不含环;如果含有环,快指针最终会超慢指针一圈,和慢指针相遇,说明链表含有环。

/**
 * 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) {
        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;
    }
};

 

142. 环形链表II(简单)

题目:

如果链表有环,找出环的起始位置

思路:

当快慢指针相遇时,让其中任一个指针指向头节点,然后让它俩以相同速度前进,再次相遇时所在的节点位置就是环开始的位置

推导:

  • 第一次相遇时,假设慢指针 slow 走了 k 步,那么快指针 fast 一定走了 2k 步:
  • fast 一定比 slow 多走了 k 步,这多走的 k 步其实就是 fast 指针在环里转圈圈,所以 k 的值就是环长度的「整数倍」。
  • 设相遇点距环的起点的距离为 m,那么环的起点距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点
  • 从相遇点继续前进 k - m 步,也恰好到达环起点
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* slow=head;
        ListNode* fast=head;
        while(fast!=NULL&&fast->next!=NULL){
            slow=slow->next;
            fast=fast->next->next;
            //当快慢指针相遇意味有环
            if(slow==fast){
                break;
            }
        }
        //如果快指针后边为空,没有环
        if(fast==NULL||fast->next==NULL){
            return NULL;
        }
        //慢指针从头,两者继续前进到相遇
        slow=head;
        while(slow!=fast){
            slow=slow->next;
            fast=fast->next;
        }
        return slow;
    }
};

 

posted @ 2022-02-26 20:36  鸭子船长  阅读(52)  评论(0编辑  收藏  举报