如何判断链表是否有环

154 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

问题引入:

怎么辨别下面两个链表的区别?,他们的结点数都相同

在这里插入图片描述

方法:快慢指针

什么是快慢指针? 顾名思义,使用两个指针,一个的位移距离比另一个要大

怎么使用快慢指针判断链表是否有环? 令两个指针都位于链表头结点,处于头指针的位置,快指针每次向后移动两个结点的位置,慢指针每次移动一个结点的位置,如果两个指针相遇了,证明有环

区分:头结点,首结点

  • 头结点是为了操作链表方便而设立的结点,里面一般不存放数据
  • 首结点才是第一个数据的存放点

下图是每一步的执行过程,在第七步,两个指针指向了同一个结点,证明了这个链表有环

在这里插入图片描述

当链表没有环的时候,快指针必然会指向NULL,因为尾结点的指针指向的就是NULL NULL 表示空 在这里插入图片描述

问题拓展:

1.怎么求出环的长度?

  1. 增加一个变量记录下指针的移动次数
  2. 当快指针和慢指针相遇的时候,快指针比慢指针多走了一个环的长度,相当于数学中的追及问题,快的一方追上慢的一方的时候,多跑了一圈
  3. 环的长度 = 速度差(快的和慢的每次移动距离的差值)* 移动的次数
  4. 环的长度相当于路程 ,速度差相当于速度 , 移动次数相当于时间 ,所以,路程等于速度乘以时间

在这里插入图片描述

上图中,序号1 是初始状态,到序号7 的时候,总共经历了六步(2,3,4,5,6,7),而速度差和移动次数的乘积正好是6,符合环的长度为6

2.如何判断环的起点(尾部连到的是哪个结点)?

  1. 把一个指针放回头结点
  2. 另一个指针保留在相遇的那个结点
  3. 令两个指针同时开始,每一次都只移动一个结点,再一次相遇的时候,便是这个环的起点

在这里插入图片描述 到第二步的时候,a , b 两个指针再一次相遇,而他们再一次相遇的这个点正好是这个环的起点(下面一行最左边的那个点为链表的头结点)