单链表带环问题

判断单链表是否带环?若带环,求环的长度?求环的入口点?


 1 2 3 4 5 6 7 8 9


不带环

链表遍历一次, 到最后的节点的下一个节点会指向NULL,此时链表不带环。

带环

,在判断链表是否带环之前,应该先判断链表是否为空。空链表肯定不带环。只要链表带环,对链表进行遍历就会形成死循环,没有出口。这是就需要用到快慢指针来确定链表是否带环。

定义两个指针(fast,和slow)同时指向链表的头节点。 fast每次走两步,slow每次走一步。(这里最好是快的比慢的多走一步,如果多了的话可能会出现问题。具体看例子。)这样的话,在进入slow进入环之后,fast肯定会在环内追上slow,如果fast追上了slow,那么就说明这个链表带环。

举个栗子:

假设有一个带环链表,1 2 3 4 5 6 7 8 9   环的入口为7,slow=slow-next;fast=fast->next->next->next; 这样的话进环之后,每次都会将fast和slow的位置互换,永远也追不上。形成死循环。

求环的长度

在此之前,我们已经知道了fast和slow的相遇点。定义一个指针meet ,定义一个计数器count。来记录这个相遇点,然后slow指针再继续遍历每次count++。直到遇到指针meet,此时的count就是环的长度。

求环的入口点。

同样,我们已经知道了相遇点,如何求入口点呢。重新定义一个指针指向头结点。然后每次指向下一个节点。同时。定义一个指针指向相遇点,每次指向下一个节点。当两个指针相遇时,就是环的入口点。

为什么呢?

设头结点到入口点的距离为a,入口点到相遇点的距离为c,相遇点到入口点的距离为c, 那么就有 2*(a+c)=a+nb+c;注意一定是nb,而不是b,加入链表很长,而环很短,那么指针从相遇点走过的路程就会是nb。

2*(a+c)=a+nb+c;      a+c=nb, a=nb-c;

而a是环的头结点到入口的距离。

判断两个链表是否相交,若相交,求交点

第一种,不带环

循环嵌套,设置两个指针list1和list2分别指向两个链表的头结点。然后遍历,当两个指针的next指针指向同一个节点时说明两个链表相交。否则不想交。

第二种,带环

带环链表判断相交问题比较复杂,可以分为下面几种情况:

1)

相交点在环外;

注意:如果相交,那么两个链表都带坏。因为单链表相交点不会有两个分别指向不同节点的next指针;

2)

相交点在环的入口;

3)

相交点在环内;

这种情况需要特别注意,相交点和入口点可以看作有两种情况,分别作为入口点或者相交点。


4)两个链表都带环但不想交;

当两个链表第二次走到环的入口处时,两个链表没有相交点。

5)一个链表带环一个不带环且不相交。

遍历两个链表后没有某一个节点的next指向同一个节点。


猜你喜欢

转载自blog.csdn.net/liuxiaokai_liu/article/details/78067911