[路飞]JavaScript:判断一个单链表是否有环和环的第一个起点

282 阅读2分钟

1.判断一个单链表是否有环()

1.利用快慢指针是否相遇来判断是否有环,如果有环快慢指针会在环里相遇。
2.慢指针和快指针在起点一起向前走,慢指针每次走一步,快指针一次走两步。
3.判断快慢指针是否相等,如果相等就是有环,返回true,不相等返回false没有环

以下是代码(快慢指针起点开始一起走):

var hasCycle = function (head) {
//判断单列表是否存在,或者只有一个节点
if(!head || !head.next) return false;
//p是慢指针,q是快指针,在起点开始
let p = q = head;
//慢指针每次走一步,快指针走两步,判断是否相等
do{
p = p.next;
q = q.next.next;
}while(p != q && q && q.next)
//走到这一步说明p和q相遇了,或者,q或q。next为空,如果q或者q.next为空说明没环,不为空就是有环
if(!q || !q.next) return false
return true
}

慢指针起点开始,快指针在第二个位置开始

var hasCycle = function (head) {
if(!head || !head.next) return false;
//定义变量p慢指针在起始点,定义快指针q在地点的下一个位置开始
let p = head,q = head.next;
//慢指针每次走一步,快指针走两步,判断是否相等
while(p != q && q && q.next){
p = p.next;
q = q.next.next
}
//走到这一步说明p和q相遇了,或者,q或q。next为空,如果q或者q.next为空说明没环,不为空就是
if(!q || !q.next) return false
return true
}

2.找环的第一个起点

1.快慢指针如果都从起点开始,慢指针每次走一步,快指针每次走两步,假如慢指针p走到第一个节点位置的时候走了a步,name快指针q就走了2a步。
2.假设现在快指针q还需要x步能追上慢指针p,那么环的总长度就是a+x,现在q需要再走x步追上p,所以剩下相遇点还需要a步能到第一个环节点,而p到第一个节点的距离也是a距离,所以我们需要找到相遇点,然后让p从起点位置开始,q在相遇点开始,每次都是走一步,等相等的时候就是第一个环节点了。代码如下:

var detectCycle = function(head) { //判断单列表是否存在,或者只有一个节点

if(!head || !head.next) return null;
//p是慢指针,q是快指针,在起点开始
let p = q = head;
//慢指针每次走一步,快指针走两步,判断是否相等
do{
p = p.next;
q = q.next.next;
}while(p != q && q && q.next)
//走到这一步说明p和q相遇了,或者,q或q。next为空,如果q或者q.next为空说明没环,不为空就是有环
if(!q || !q.next) return null
//此时p和q相遇,相遇点到第一个节点的距离,和起点到第一个节点距离相等,所以让p等于起点,相等就是第一个节点了
p = head;
while(p != q ){
p = p.next;
q = q.next;
}
return p;
};