两种思路:
①思路
第一步、设置快慢指针,假如有环,他们最后一定相遇。
第二步、两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。
快指针路程=a+(b+c)k+b ,k>=1 其中b+c为环的长度,k为绕环的圈数(k>=1,即最少一圈,不能是0圈,不然和慢指针走的一样长,矛盾)。
慢指针路程=a+b
快指针走的路程是慢指针的两倍,所以:
(a+b)*2=a+(b+c)k+b
化简可得:
a=(k-1)(b+c)+c 这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度。其中k>=1,所以k-1>=0圈。所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
function EntryNodeOfLoop(pHead)
{
// write code here
if(pHead==null || pHead.next==null || pHead.next.next == null){
return null
}
let fast = pHead.next.next;
let slow = pHead.next;
while(fast&&slow){
if(fast!==slow){
fast=fast.next.next;
slow=slow.next;
}
else{
break;
}
}
if(fast==null||slow==null){
return null
}
fast = pHead;
while(fast!==slow){
fast=fast.next;
slow=slow.next;
}
return fast
}
②思路
第一步、找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。
第二步、找环的长度。从环中的相汇点开始, p2不动, p1前移, 当再次相遇时,p1刚好绕环一周, 其移动即为环的长度K
第三步、求换的起点, 转换为求环的倒数第N-K个节点,则两指针left和right均指向起始, right先走K步, 然后两个指针开始同步移动, 当两个指针再次相遇时, right刚好绕环一周回到起点, left则刚好走到了起点位置
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function EntryNodeOfLoop(h)
{
if(h===null||h.next===null||h.next.next===null)return null;
var p,q;
p = h.next;
q = h.next.next;
while(p != q){
q = q.next;
p = p.next.next;
}
p = p.next;
var count = 1;
while(p != q){
p = p.next;
count++;
}
p = h;
q = h;
while(count != 0){
q = q.next;
count--;
}
while(p != q){
q = q.next;
p = p.next;
}
return q;
// write code here
}