[2014校招笔试]判断单链表是否有环?

某互联网企业的笔试题:判断单链表是否有环?如果有环,如何在O(N)的时间复杂度和O(1)的空间复杂度得到这个环的入口点?

问题1:如何判断有环呢?

这个方法可能不只一种,但是在网上看到的那个类似于两个人跑步的解法最容易让人接受。两个人跑步,同时跑,但一个人在跑的快,一个人跑的慢,如果他们在一个环形操场上跑的话,肯定他们要不只一次的相遇。判断环也是这个原理,两个指针p和q,一开始p和q都指向头结点,如果p每次移动一步,q每次移动两步,那么p和q如果再一次相遇,那么有环,如果走到null,那么肯定没环。

问题2:如何得到环的入口?

这个需要一点的推导,假设在p和q第二次相遇的时候(第一次相遇在头结点)p走了s步,那么q肯定走了2s步,所以有:

2*s-s=nr.  其中,r是环的长度,n是圈数。

如果记从头结点到环入口点的距离为a,从换入口点到相遇点得距离为x,那么有

s=a+x. (q和p相遇时,p肯定没有走完一圈)

由上面两个公式又能推出:

s=a+x=nr

如果链表总长度为L的话,那么r=L-a, 有

a+x=(n-1)r+(L-a)

a=(n-1)r+(L-a-x)

其中L-a-x是p要走完一圈还要走的步数。

因此可以这样找到环的起始点:p和q相遇后,再增加一个指针k,k指向链表的头结点,然后k开始移动,一次一步,p继续移动,一次一步,那么当k走到环的入口点,p也一定到了环的入口点。因此k和p的相遇点,就是换的入口点。

 

扩展问题1:如何求循环链表上任一点a的最远点b.

一个圆上最远点就是同一条直径上的另一个点嘛。

方法还是指针p和q, 均从a点出发,p一次走1步,q一次走2步,当q回到a时,p指的点就是另一端的点。因为q走一圈的时候,p肯定只走了半圈。

 

扩展问题2:判断两个单链表是否相交,如果相交,给出相交的第一个点(两个链表都不存在环)

其实只要把第一链表首位相连,判断相交和找相交点就变成了与问题1和2相同的问题。

其实判断两个单链表是否相交有更简单的方法,只需要判断链表的最后一个点是否相同就可以。因为如果相交,就像轨道并轨一样,两个链表的最后一个节点肯定是相同的。

还可以通过两个栈来得到第一个相交的点,将Link A的节点全部压入栈SA,将Link B的节点全部压入栈SB,然后同时出栈,最后一个相同的点就是相交点。

还有另外一种判断方法,容易得到Link A的长度LA,和Link B的长度LB,那么假设LA>LB那么LA先走LA-LB步,LB在从走,两个指针肯定会相交,相交的第一个点就是要找的点。

 

 

 

posted @ 2013-09-29 17:02  orchid  阅读(505)  评论(0编辑  收藏  举报