目录
前言
单链表带环是链表中比较经典的问题,重要是推导和证明
一、什么是环形链表?
链表中最后节点的next不是链接到NULL,而是链接到该链表中任一节点包括自己


二、如何判断链表是否是环形链表呢
我们这里运用到了快慢指针
思路:
slow走一步,fast走两步,如果没有环,fast在会NULL或者是fast->next为NULL就结束(取决于链表的长度),有环fast和slow就会相遇
三种情况:
- fast进环(在环入口),slow走了一半
- slow进环(在环入口),fast已经在环内走了一段路(这里取决于环的长度,可能走了几圈了,可能一圈都没有走完)
- fast开始追击slow,直到最后相遇



1. 假设slow刚进环时,fast与slow之间的距离为N,环的长度为C
- slow每次走1步,fast每次走2步,一定可以相遇吗?
- slow每次走1步,fast每次走3步,一定可以相遇吗?
- slow每次走1步,fast每次走4步,一定可以相遇吗?
2.slow每次走1步,fast每次走2步,一定可以相遇吗?
每次追击,fast和slow的距离就在减1,N,N-1,N-2,…,0,最后一定能相遇
所以这种情况一定能相遇


3.slow每次走1步,fast每次走3步,一定可以相遇吗?
每次追击,fast和slow距离就减2,就需要对N分情况
(1) N是偶数,N-2,N-4,N-6,…,0,那就可以相遇
(2) N是奇数,N-2,N-4,N-6,…,1,-1。-1的意思是fast刚好超过了slow1步,现在fast就需要追C-1的长度,相当于C-1 = N,现在能否相遇就取决于C的长度
- 如果C-1是
偶数,就可以相遇 - 如果C-1是
奇数,就永远不会相遇,因为C-1是奇数,fast追击还是会超1步,陷入死循环了,永远都超slow1步

4.slow每次走1步,fast每次走4步,一定可以相遇吗?
每次追击,fast和slow距离就减3,就需要对N分情况
(1)N是3的倍数,N-3,N-6,N-9,…,0,那就可以相遇
(2)N不是3的倍数,需要对fast和slow相差的步数分情况
- 最后fast超slow1步,C-1 = N,就是C-1必须要是3的倍数,才能相遇,否则永远不相遇
- 最后fast超slow2步,C-2 = N,就是C-2必须要是3的倍数,才能相遇,否则永远不相遇
总结:只有slow走1步,fast走2步,每步差距为1的情况下,一定能相遇,其他情况每步差距 > 1,取决于N(fast和slow相差的距离)和C(环的长度)。
四、OJ:环形链表 I
OJ链接
思路:
通过快慢指针,slow走1步,fast走2步,是环形链表两个指针一定能相遇,fast=NULL或fast->next=NULL,就不是环形链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
struct ListNode* slow, *</

本文详细介绍了如何使用快慢指针判断链表是否为环形链表,以及如何找到环形链表中的入环结点。通过实例分析不同步长情况下相遇条件,并提供了两种OJ解题思路:一是利用环形链表的特性重新构造相交链表,二是直接在原链表上操作,避免修改链表结构。
最低0.47元/天 解锁文章
1253





