判断链表是否有环
思路一:快慢指针
(1)定义两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个指针一次走两步
(2)如果走得快的指针追上了走得慢的指针,那么链表就是环形链表;
如果走得快的指针走到了链表的末尾(next指向 NULL)都没有追上第一个指针,那么链表就不是环形链表。
fast 要比 slow 移动的快,如果有环,fast 一定会先进入环,而 slow 后进入环。
(2)如果走得快的指针追上了走得慢的指针,那么链表就是环形链表;
如果走得快的指针走到了链表的末尾(next指向 NULL)都没有追上第一个指针,那么链表就不是环形链表。
fast 要比 slow 移动的快,如果有环,fast 一定会先进入环,而 slow 后进入环。
当两个指针都进入环之后,经过一定步的操作之后二者一定能够在环上相遇,并且此时 slow 还没有绕环一圈(fast可能已经走完了n>=1圈了),也就是说一定是在 slow 走完第一圈之前相遇。
思路二:STL中map表进行映射
(1)定义 map<NODE *, int> m; 将一个 NODE * 指针映射成数组的下标,并赋值为一个 int 类型的数值。
(2)从链表的头指针开始往后遍历,每次遇到一个指针p,就判断 m[p] 是否为0。
如果为0,则将m[p]赋值为1,表示该节点第一次访问;
如果m[p]的值为1,则说明这个节点已经被访问过一次了,于是就形成了环。
拓展1:计算环的长度n
从这个快慢指针相遇的节点出发,一边继续向前移动一边计数,当再次回到这个节点时,即可得到环中的节点数n了。拓展2:找到环的入口结点
(1)定义两个指针p1和p2,在初始化时都指向链表的头节点。(2)如果链表中的环有n个节点,指针p1先在链表上向前移动n步。
(3)然后指针p1和p2以相同的速度在链表上向前移动直到它们相遇。
(4) 它们相遇的节点就是环的入口节点。