链表问题收集

存在环的单链表

一.判断单链表是否存在环

方法1:基本方法,每遍历一项,为此项打上已遍历标记,具体可能用Hash表存储的方式,后面若访问到了已遍历的点则说明有环。space-O(n),time-O(n)。

方法2:使用p,q两个指针,p总是向前推进。p每推进一步,q均从头遍历到p的位置为止。记录双发走的步数,如果步数不一样,则有环。space-O(1),time-O(n^2)。

方法3:使用快慢指针,slow每次走一步,fast每次走2步,如果fast遇到null之前fast和slow还没相遇,则说明无环,若相遇则有环。space-O(1),time-O(n)。

显然方法三是最优的!

二.求环的长度

在方法3中,在相遇的点开始走,第二次到达相遇点所走的长度就是环的长度。

三.找出环的连接点

设链表头到环入口结点的结点数目是a,环内的结点数目r。假设相遇时,fast指针已经绕环转了n圈,比slow多走了n*r步。

 假设环的入口结点到相遇结点的结点数目为x。那么在相遇时,slow走了a+x步,fast走了a+x+n*r步。

由于fast的步调是slow的两倍,所以有a+x = n*r。因而,a = n*r - x。显然,从相遇位置开始,走n*r - x步,一定可以到达环的入口结点;

从链表头开始,走a步,也会到达环的入口。并且我们得到了a = n*r - x。

所以我们让两个指针,一个从相遇位置出发一个从链表头出发,让他们都单步前进。因为a = n*r - x,所以他们一定会在环的入口相遇。


两个链表相交问题

一.如何判断单链表是否交叉?

如果两个链表相交,必然是Y字形,所以判断两个链表的最后一个节点是不是相同即可;

二.如何找出出交叉在哪里?

根据两个链表的长度差 m-n,长的先走m-n步,短的从头开始走,相遇点即为交点;

三.如果可能有环呢?

先判断两个链表有没有环,如果都没环(已解决),有一个有环一个没环,它们肯定不相交;如果都有环,如何判断? 
a) 从链表1的环里随便找一个节点A(用一快一慢两指针找),看是不是在链表2里,在则相交;不在不交。 
b) 求交点:求出链表1和链表2从头到A的步数,相减,和前面找交点的方法一样处理。


在O(1)时间删除链表结点

问:给定链表的头指针和一个节点指针,在O(1)时间删除该节点。

答:将下一结点数据复制到当前结点,然后删除下一结点。所谓的狸猫换太子思想。




参考:

http://fayaa.com/tiku/view/7/

http://wuchong.me/blog/2014/03/25/interview-link-questions/

http://fayaa.com/tiku/view/8/



你可能感兴趣的:(链表问题收集)