单链表中判断是否有环以及得出环的入口点(简单易懂)

来源:互联网 发布:淘宝商家服务 编辑:程序博客网 时间:2024/06/05 07:24

看了书上的讲解,关于得出环的入口点的计算公式着实挺难理解,而且又没有配图,网上看到的几篇博客大多照搬书上的讲解。我在理解了思想之后尝试用自己的语言表达一下我的解法思路,很简单。

1.       判断单链表是否有环

这是很多公司入门级的面试笔试题。单链表由于每个结点只有一个next指针指向下一个结点,不存在其他指针,所以一旦进入环里,就再也出不去了。类似于下图(像一个烤盘)

      

那么怎么样判断单链表是否有环呢?方法很简单,把环看作操场,两位选手在操场上赛跑,一个速度快,一个速度慢,如果他们一直跑,快的选手肯定会在第一次超过慢的选手之后再次追上慢的选手,与他相遇;若现在没有环,那么快的选手将始终跑在慢的选手前面,不可能有第二次相遇。所以我们判断一个链表是否有环的方法就是基于这个思想:

        在链表头部设两个指针,一个每次向后移动两个位置(快指针),另一个每次向后移动一个位置(慢指针)。这相当于在起点设置了两位跑步选手,跑的快的选手的速度是慢的选手的两倍。接下来两个指针在遍历链表过程中,如果快指针到达链表尾还没有和慢指针相遇,说明链表无环,反之说明有环。

 

2.       获得环的入口点

书上说的公式挺复杂的,我们这里只要考虑两个指针第一次相遇的情况就好了。第一次相遇的条件是:快指针在环内比慢指针多走了一圈。如下图所示,两个指针从起点O出发,在环中的B点相遇,现在我们的目标是如何根据B点找到A点这个结点。注意:结点在环中的前进方向是顺时针,即A→B→A.

              

毫无疑问,两个指针第一次在B点相遇时:

慢指针走过的路程是:

S_slow = |OA| +|AB| = x + y.

 快指针走过的路程是:

S_fast =  |OA| + |AB| + |BA| + |AB| = x + y + z + y.

又因为快指针的速度是慢指针的两倍,所以在相同时间内快指针走过的路程是慢指针的两倍,所以

  S_fast = 2 * S_slow

 即 

 2(x + y) = x + y + z + y.

 求得 

z = x.

所以说明

|BA| = |OA|.

所以在两个指针相遇后,将慢指针移到O点起始位置,即链表头指针位置,快指针仍然在B点。然后它们一起向前移动,每次移动一个位置,由于|BA| = |OA|, 所以他们最终肯定会在A点相遇,A点这个相遇点就是环的入口点。

 

代码很简单,就不贴了。

0 0