环形链表(给定一个链表的头节点 head ,返回链表开始入环的第一个节点)的原理讲解

一:题目

二:原理讲解

解决这个题目 ,我们得先理解它的原理。

1:

首先假设两个指针,一个快指针fast,一个慢指针slow,fast一次移动两个节点,slow一次移动一个节点。(前面的直线代表进入环前面的节点,后面的圆圈就代表入环后的所有节点)

由博主前文环形链表(判断链表中是否有环)的讲解-CSDN博客可知,如果这是一个带环链表,那么二者fast和slow,最后会在环里相遇。 

2:

二者相遇

第一种情况:

此时:我们假设起点到入口点的距离为L,环的周长为C,入口点到相遇点的距离为X。

因为:在截止相遇的那一刻,fast走的距离是slow的两倍。

由上图可知,slow走的距离为L+X,fast走的距离是L+C+X,

所以 2(L+X )= L+C+X,化简可得,L = C - X。

L = C - X是什么意思,意思就是,如果一个点从相遇点开始走(相遇点到入口点的距离是C-X),一个点从起点开始走(起点到入口点的距离是L),他们会在入口点相遇。

这个结论的意义是什么?

意义在于 :入口点就是我们题目要求的入环的第一个节点,而相遇点我们在前文中环形链表(判断链表中是否有环)的讲解-CSDN博客可以轻松得到。

但是这个分析是不完整的。

不完整的原因:

(因为还有第二种情况)

如果L = C - X,由图可知,当环比较小的时候,比如图中的C=4,进环前的节点很多的时候。

L = C - X,在这种情况下不会成立。

3:

完整的分析:

fast走的路程的确是slow 的两倍,但是fast不一定只是L+C+X,在第二种情况我们可以知道,fast应该在slow进入环之前,就已经可能在这个环内走了几圈。

所以正确的表达式应该是:2(L+X )= L+ n * C + X 。 

n代表走的圈数:

由情况1可知,在slow进入环之前,fast在环内走的长度一圈都没有,在slow进入环后,fast开始追赶,最后走了一点距离,追上了slow,此时fast在slow进入环之前在环里走的距离+在slow进入环之后在环里追击所走的距离= 一圈,所以n的最低取值为1。(n≥1)

将2(L+X )= L+ n * C + X ,化简得到:L =  C - X + (N-1) * C。

怎么理解 情况2 的结论:L =  C - X + (N-1) * C  和 情况1: L = C - X  的区别?

情况1:如果一个指针a从相遇点开始走,一个指针b从起点开始走,他们会在入口点相遇。

情况2:如果一个指针a从相遇点开始走,一个指针b从起点开始走,他们会在入口点相遇。

看似两者一致,但是区别在于:

情况1:a指针从相遇点开始走到和b指针在入口点相遇的时候,a指针在环内只走了 C - X,一圈不到的长度。

情况2:a指针从相遇点开始走到和b指针在入口点相遇的时候,a指针在环内走了 C - X + (N-1) * C ,走了N-1圈 ,然后再走了C - X 的长度。

代码展示:

结论:当我们通过快慢指针得到相遇节点,一个指针从相遇节点开始走,一个指针从起点开始走,二者会在环的入口节点相遇。 

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值