“这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战”
题目 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路
解决这个问题可以分三步。
(1)第一步是确定一个链表中是否包含环。我们可以用两个指针来解决这个问题。定义两个指针,同时从链表的头结点出发,一个指针一次走一步,另一个指针一次走两步。如果走得快的指针追上了走得慢的指针,那么链表就包含环;吐过走得快得快的指针走到了链表的末尾(ListNode的next指向null)都没有追上第一个指针,那么链表就不包含环。
(2)第二步是找到环中节点的数目,这一步的目的就是为寻找环的入口做铺垫。我们在上面提到判断一个链表里面是否有环时用到了一快一慢两个指针。如果两个指针相遇,则表明链表中存在环。两个指针相遇的节点一定是在环中。可以从这个节点出发,一边继续向前移动一边计数,当再次回到这个节点时,就可以得到环中节点数了。
(3)第三步是找到环的入口。我们还可以利用两个指针来解决这个问题。先定义两个指针P1和P2指向链表的头结点。如果链表中的环有n个节点,则指针P1先在链表上向前移动n步,然后两个指针以相同的速度向前移动。当第二个指针指向环的入口节点时,第一个指针已经围绕着环走了一圈,又回到了入口节点。
代码
// 1,快慢指针 floyd算法
// a,找相遇点 b,找入口
function EntryNodeOfLoop(pHead) {
var fast = pHead;
var slow = pHead;
if(pHead === null || pHead.next === null)
return null;
//快指针速度为慢指针速度的两倍
while(fast !== null && fast.next !== null) {
if(fast.next.next === slow.next)
break
//此时两节点相遇
}
//现在速度相同,且慢指针还在相遇的位置,此时头节点到入口节点的距离等于
//相遇节点到入口节点的距离,此时相同速度往前走会在入口节点相遇
fast = pHead;
while(fast !== slow){
slow = slow.next;
fast = fast.next;
}
return slow;
}