链表专项之环形链表

简介: >给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回 true 。 否则,返回 false 。

@TOC


前言


1.141. 环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

  在这里插入图片描述
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast!=NULL&&fast->next!=NULL)
    {
        slow=slow->next;
        fast=fast->next->next;
         if(slow==fast)
        {
            return true;
        }
    }
   return false; 
}

这道题的思考还是比较简单的 使用快慢指针

两者从head开始

快指针每次走2步

慢指针每次走1步

如果是循环链表则 一定能使快指针追上慢指针

也要注意一个问题 判断slow指针与fast指针是否相等 ,是在移动一次之后

因为 开始定义的时候就是相等的

证明为什么快指针一定为2步,慢指针一定为1步

1.当循环链表前的距离与循环链表后的距离相等时

在这里插入图片描述

>当slow指针走到循环开始时,fast指针已经走完一圈了,所以两者处于相同位置

### 2.当循环链表前的距离为循环链表后的距离的1/2

在这里插入图片描述

fast一次走2步,slow一次走1步

当slow走到循环开始的位置, fast已经走到循环的一半

按照顺时针的顺序 fast追slow,  两者之间的距离为x

当fast与slow每走一次则之间的距离减少1

即x-1,x-2,x-3,x-4,x-5,x-6……..

无论x为奇数或者偶数 两者一定能相遇

同种情况下,fast走N步,slow走1步

依旧假设fast指针与slow指针之间的距离为x

若fast指针一次走3步,slow指针一次走1步

则slow与fast每走一次距离减少2

x-2,x-4,x-6,x-8,x-10…..

x若为偶数则能成功遇见 ,若为奇数 就会一直错过 ,造成死循环

同理 若fast指针一次走4步,slow指针一次走1步

两者之间每次减少3

x-3,x-6,x-9,x-12…..

若x为奇数则能成功遇见,若为偶数 就会一直错过,造成死循环

142. 环形链表 II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

  在这里插入图片描述
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
           struct ListNode*cur=slow;
            while(head!=cur)
            {
                cur=cur->next;
                head=head->next;
            }
            return cur;
        }
    }
     return NULL;
}

这道题需要一个公式,这个公式需要推导下

它分为 正常情况与特殊情况

公式的推导

### 1.正常情况

在这里插入图片描述

fast走2步,slow走1步

没循环的链表距离为L ,slow在循环链表中走的距离为X,循环链表一圈距离为C

slow走的长度为L+X,fast在循环链表为L+C+X

当fast与slow相遇时 fast是slow走的2倍

即 2(L+X)=L+C+X

L=C-X

相当于head到交点的距离等于相遇点到交点的距离

在这里插入图片描述

### 2.特殊情况

 >

在这里插入图片描述  

没循环的链表距离为L ,slow在循环链表中走的距离为X,循环链表一圈距离为C

当循环链表C很小时

则当slow刚进入循环时,fast已经转了N圈

当fast与slow相遇时

即 2(L+X)=L+N  * C+X

即 L=N*C-X

此时的N * C代表从相遇点处开始的N圈 减去x正好为相遇点

所以N的数量不会影响

依旧从fast与slow的相遇点开始 到交点的距离与head到交点的距离相等

目录
相关文章
|
5月前
|
Java
环形数组链表(java)
环形数组链表(java)
|
1月前
【数据结构】环形、相交、回文、分割、合并、反转链表
【数据结构】环形、相交、回文、分割、合并、反转链表
28 0
|
4月前
【数据结构OJ题】环形链表
力扣题目——环形链表
37 3
【数据结构OJ题】环形链表
|
4月前
【数据结构OJ题】环形链表II
力扣题目——环形链表II
30 1
【数据结构OJ题】环形链表II
|
5月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
52 2
|
4月前
|
Java 索引
力扣经典150题第五十六题:环形链表
力扣经典150题第五十六题:环形链表
33 0
|
5月前
|
Java
单向环形链表-约瑟夫问题(java)
单向环形链表-约瑟夫问题(java)
|
5月前
|
存储 算法 C语言
【数据结构与算法 刷题系列】环形链表的约瑟夫问题
【数据结构与算法 刷题系列】环形链表的约瑟夫问题
|
6月前
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
53 1
|
6月前
|
存储 算法 索引
【力扣刷题】只出现一次的数字、多数元素、环形链表 II、两数相加
【力扣刷题】只出现一次的数字、多数元素、环形链表 II、两数相加
51 1